package Merlion.CRM.bean;

import Merlion.CRM.entity.PurchaseOrderEntity;
import Merlion.CRM.entity.LineEntryEntity;
import Merlion.CRM.entity.CustomerEntity;
import Merlion.CRM.entity.SalesOrderEntity;
import Merlion.CRM.entity.SalesInquiryEntity;
import Merlion.CRM.entity.BillingAddressEntity;
import Merlion.CRM.entity.PricebookEntity;
import Merlion.CRM.entity.ShippingAddressEntity;
import Merlion.CRM.entity.SalesDocumentEntity;
import Merlion.CRM.entity.ClientEntity;
import Merlion.CRM.entity.ContactEntity;
import Merlion.CRM.entity.DeliveryOrderEntity;
import Merlion.CRM.entity.QuotationEntity;
import Merlion.CRM.entity.SalesLeadEntity;
import Merlion.FRM.bean.CreditProfileBeanRemote;
import Merlion.FRM.bean.PaymentBeanRemote;
import Merlion.MRP.bean.DemandManagementBeanRemote;
import Merlion.MRP.bean.ProductionManagementBeanRemote;
import Merlion.SCM.bean.InventoryItemsBeanRemote;
import Merlion.SCM.bean.InventoryMovementsManagementBeanRemote;
import Merlion.SCM.entity.PickingOrderEntity;
import Merlion.SCM.entity.PickingOrderEntryEntity;
import Merlion.SCM.entity.ProductEntity;
import Merlion.util.state.AddressState;
import Merlion.util.state.ClientState;
import Merlion.util.state.LineEntryState;
import Merlion.util.state.ProductState;
import Merlion.util.state.SalesDocumentState;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collection;
import java.util.Date;
import java.util.List;
import javax.ejb.EJB;
import javax.ejb.Stateless;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;
import Merlion.util.state.ATPCheckState;
import Merlion.util.state.DeliveryOrderState;
import Merlion.util.state.PricebookEntryState;
import Merlion.util.state.PricebookState;
import Merlion.util.state.WarehouseState;
import java.text.DecimalFormat;

@Stateless
public class SalesOrderProcessingModuleBean implements SalesOrderProcessingModuleRemote {

    @PersistenceContext
    EntityManager em;
    @EJB
    private SalesLeadModuleRemote smb;
    @EJB
    private DemandManagementBeanRemote dmb;
    @EJB
    private CreditProfileBeanRemote cpb;
    @EJB
    private InventoryMovementsManagementBeanRemote imm;
    @EJB
    private InventoryItemsBeanRemote iib;
    @EJB
    private PaymentBeanRemote pbr;
    @EJB
    private MessageManagerBeanRemote mmb;
    @EJB
    private ProductionManagementBeanRemote pmb;

    public String removeLineEntry(Long salesDocId, Long lineEntryId) {

        System.out.println("Remove line entry");
        String result;

        System.out.println("Find the corresponding sales document");
        SalesDocumentEntity sd = em.find(SalesDocumentEntity.class, salesDocId);
        
        if (sd != null && sd.getDeleteFlag().equals("N")) {
            Collection<LineEntryEntity> lineEntryList = sd.getLineEntryList();
            for (Object o : lineEntryList) {
                LineEntryEntity lineEntry = (LineEntryEntity) o;
                if (lineEntry.getId().equals(lineEntryId)) {
                    lineEntryList.remove(lineEntry);
                    em.flush();
                }
            }
            result = "Remove succesful";
        } else {
            System.out.println("Sales document not found.");
            result = "Remove failed, no document found.";
        }

        return result;
    }

    public String editLineEntry(Long id, int quantity, double price, String type) {

        System.out.println("Edit line entry");
        String result;

        LineEntryEntity le = em.find(LineEntryEntity.class, id);

        if (le != null & le.getDeleteFlag().equals("N")) {

            le.setQuantity(quantity);
            le.setPrice(price);
            em.flush();
            double total = getTotalPrice(le, type);
            le.setTotalLinePrice(total);
            em.flush();
            result = "Inquiry edited";
        } else {
            System.out.println("Inquiry not found.");
            result = "Failed, no inquiry found";
        }

        return result;
    }

    public Long addSalesInquiry(Date dateIssued, Long clientId, Long contactId, List<LineEntryState> products,
                                String description, String docName, String pricingType) {

        System.out.println("Add Sales inquiry");
        Long salesInquiryId;

        String status = "Waiting for Confirmation";

        System.out.println("Find client");
        ClientEntity client = em.find(ClientEntity.class, clientId);
        
        if (client != null && client.getDeleteFlag().equals("N")) {
            
            System.out.println("Client found");
            SalesInquiryEntity inquiry = new SalesInquiryEntity();
            Collection<LineEntryEntity> lineEntryList = new ArrayList<LineEntryEntity>();

            if (!products.isEmpty()) {
                System.out.println("Test :: Line entry state is not null");
            }
    

            for (Object o : products) {
                System.out.println("Iterate through each line entry state");
                LineEntryState line = (LineEntryState) o;
                
                System.out.println("Find product");
                ProductEntity product = em.find(ProductEntity.class, line.getItemId());
                
                String itemName = "";
                double basePrice = 0;
                
                if (product != null) {
                    System.out.println("Product not null, get itemn name and base price");
                    itemName = product.getName();
                    basePrice = product.getBasePrice();
                    System.out.println("Item Name is :" + itemName+" Base Price:" +basePrice);
                }
                
                int quantity = line.getQuantity();
                double price = line.getPrice();
                Long itemId = line.getItemId();
                
                System.out.println("Create new line entry");
                LineEntryEntity lineEntry = new LineEntryEntity();
                lineEntry.create(itemId, itemName, quantity, basePrice, price, product);
                lineEntry.setTotalLinePrice(line.getTotalPrice());
                lineEntry.setPricebookId(line.getPricebookId());
                lineEntryList.add(lineEntry);
                System.out.println("Persist line entry");
                em.persist(lineEntry);

            }
            
            System.out.println("Create sales inquiry");
            inquiry.create(lineEntryList, dateIssued, "SI", client);
            System.out.println("Persist Sales Inquiry");
            em.persist(inquiry);
           
            System.out.println("Test ::  Contact not null?");
            if (contactId != null) {
                System.out.println("Contact Id is not null, find contact entity");
                ContactEntity contact = em.find(ContactEntity.class, contactId);
                inquiry.setContact(contact);
            }
            
            inquiry.setStatus(status);
            inquiry.setDescription(description);
            inquiry.setDocumentName(docName);
            inquiry.setPricingType(pricingType);
            em.flush();
            
            salesInquiryId = inquiry.getId();
            
        } else {
            System.out.println("Client not found.");
            String zero = "0";
            salesInquiryId = Long.parseLong(zero);
        }

        System.out.println("Return value is : "+ salesInquiryId);
        return salesInquiryId;
    }

    public String deleteSalesInquiry(Long id) {

        System.out.println("Delete sales inquiry");
        String result;


        System.out.println("Find sales inquiry");
        SalesInquiryEntity inquiry = em.find(SalesInquiryEntity.class, id);
        
        if (inquiry != null && inquiry.getDeleteFlag().equals("N")) {
            System.out.println("If sales inquiry is found, set delete flag to Y");
            inquiry.setDeleteFlag("Y");
            em.flush();
            
            System.out.println("Find line entry list");
            Collection<LineEntryEntity> lineEntryList = inquiry.getLineEntryList();
            for (Object l : lineEntryList) {
                System.out.println("Line entry found, set delete flag to Y");
                LineEntryEntity lineEntry = (LineEntryEntity) l;
                lineEntry.setDeleteFlag("Y");
                em.flush();
            }

            result = "Inquiry deleted";
        } else {
            result = "Delete inquiry failed, no inquiry found";
        }
        
        System.out.println("Result is " +result);
        return result;
    }

    public String editSalesInquiry(Long id, Date dateIssued, Long clientId, String status, String description, String docName) {
        
        System.out.println("Edit sales inquiry");
        String result;
        
        System.out.println("Find sales inquiry");
        SalesInquiryEntity inquiry = em.find(SalesInquiryEntity.class, id);

        if (inquiry != null && inquiry.getDeleteFlag().equals("N")) {
            System.out.println("If sales inquiry not null");
            inquiry.setDateIssued(dateIssued);
            inquiry.setDocumentName(docName);
            inquiry.setDescription(description);
            
            System.out.println("Find client or Sales Lead");
            ClientEntity client = em.find(ClientEntity.class, clientId);

            if (client != null && client.getDeleteFlag().equals("N")) {
                System.out.println("Client found, set client");    
                inquiry.setClient(client);
            }
            
            em.flush();
            inquiry.setStatus(status);
            inquiry.setDescription(description);
            em.flush();
            
            result = "Inquiry edited";
        } else {
            System.out.println("Inquiry not found");
            result = "Edit failed, no inquiry found";
        }

        System.out.println("Result is "+result);
        return result;
    }

    public String convertInquiryToQuotation(Long id, double discount, Date validUntil, String docName, String description) {

        System.out.println("Convert inquiry to quotation.");
        String result;
      
        System.out.println("Find sales inquiry");
        SalesInquiryEntity inquiry = em.find(SalesInquiryEntity.class, id);

        if (inquiry != null && inquiry.getDeleteFlag().equals("N")) {
            System.out.println("If sales inquiry is not null");
            QuotationEntity quotation = new QuotationEntity();
            Collection<LineEntryEntity> lineEntryCollection = inquiry.getLineEntryList();
            List<LineEntryEntity> lineEntryList = new ArrayList<LineEntryEntity>(lineEntryCollection);
            ClientEntity client = inquiry.getClient();

            String pricingType = inquiry.getPricingType();
            
            System.out.println("Get date now");
            Calendar currentDate = Calendar.getInstance();
            SimpleDateFormat formatter = new SimpleDateFormat("dd/MM/yyyy");
            Date dateNow = currentDate.getTime();

            List<LineEntryState> lineEntryStateList = new ArrayList<LineEntryState>();
            for (Object o : lineEntryList) {
                LineEntryEntity line = (LineEntryEntity) o;
                
                Long itemId = line.getItemId();
                String itemName = line.getItemName();
                int quantity = line.getQuantity();
                double price = line.getPrice();
                
                LineEntryState les = new LineEntryState(itemId, itemName, quantity, price);
                les.setId(line.getId());
                les.setIndicativeLeadTime(line.getLeadTime());
                les.setBasePrice(line.getBasePrice());
                les.setTotalPrice(line.getTotalLinePrice());
                les.setAmountInvoiced(line.getAmountInvoiced());
                les.setAmountShipped(line.getAmountShipped());
                les.setPricebookId(line.getPricebookId());
                les.setPricingType(quotation.getPricingType());

                lineEntryStateList.add(les);
            }
            
            Long contactId;
            System.out.println("Test :: Contact not null?");
            if (inquiry.getContact() != null) {
                System.out.println("Contact Id not null");
                contactId = inquiry.getContact().getId();
            } else {
                contactId = null;
            }
            
            System.out.println("Create new quotation");
            addQuotation(dateNow, client.getId(), contactId, validUntil, lineEntryStateList, description, docName, pricingType);
            em.flush();
            
            System.out.println("Set inquiry status to Converted");
            inquiry.setStatus("Converted");
            inquiry.setReferred(true);
            em.flush();
            
            result = "Inquiry converted";
            
        } else {
            result = "Conversion failed, no inquiry found";
        }

        System.out.println("Result is: "+result);
        return result;
    }

    public ATPCheckState getLeadTimeForSO(Long salesDocId, Long itemId, int demand, int bufferDays, int indicativeLeadTime, boolean isSalesOrder) {
        
        System.out.println("Get Lead time for Sales order, return ATPCheckState");
        Calendar currentDate = Calendar.getInstance();
        Date checkingDate = currentDate.getTime();
        int option;
        if (!isSalesOrder) {
            option = 1;

        } else {
            option = 2;
        }

        System.out.println("Calling demand management bean to calculate lead time");
        ATPCheckState atp = dmb.calculateLeadTime(salesDocId, itemId, demand, checkingDate, bufferDays, indicativeLeadTime, option);
        System.out.println("SOP : LEAD TIME : " + atp.getLeadTime());
        return atp;
    }

    public int getLeadTime(Long salesDocId, Long itemId, int demand, int bufferDays, int indicativeLeadTime, boolean isSalesOrder) {

        System.out.println("Get Lead time for Quotation");
        Calendar currentDate = Calendar.getInstance();
        Date checkingDate = currentDate.getTime();
        int option;
        if (!isSalesOrder) {
            option = 1;

        } else {
            option = 2;
        }

        ATPCheckState atp = dmb.calculateLeadTime(salesDocId, itemId, demand, checkingDate, bufferDays, indicativeLeadTime, option);
        System.out.println("SOP : LEAD TIME : " + atp.getLeadTime());
        return atp.getLeadTime();

    }

    public Long addQuotation(Date dateIssued, Long clientId, Long contactId, Date validUntil,
                            List<LineEntryState> products, String description, String docName,
                            String pricingType) {
        
        System.out.println("Add Quotation");
        Long quotationId = Long.parseLong("0");

        String status = "Waiting for Confirmation";

        System.out.println("Find client");
        ClientEntity client = em.find(ClientEntity.class, clientId);
        if (client != null && client.getDeleteFlag().equals("N")) {
            System.out.println("Client found");
            QuotationEntity quotation = new QuotationEntity();
            Collection<LineEntryEntity> lineEntryList = new ArrayList<LineEntryEntity>();

            
            if (!products.isEmpty()) {
                System.out.println("Test :: line entry state not null");
            }
       
            
            int totalLeadTime = 0;
            
            for (Object o : products) {
                
                LineEntryState line = (LineEntryState) o;
                System.out.println("Find product");
                ProductEntity product = em.find(ProductEntity.class, line.getItemId());
                
                String itemName = "";
                double basePrice = 0;
                double listprice = 0;
                if (product != null) {
                    System.out.println("If product not null, get item name and base price");
                    itemName = product.getName();
                    basePrice = product.getBasePrice();
                    System.out.println("Item name: "+itemName+" Base Price : "+basePrice);
                }
                
                int quantity = line.getQuantity();
                double price = line.getPrice();
                Long itemId = line.getItemId();
               
                LineEntryEntity lineEntry = new LineEntryEntity();
                System.out.println("Create line entry object");
                lineEntry.create(itemId, itemName, quantity, basePrice, price, product);
                lineEntry.setTotalLinePrice(line.getTotalPrice());
                lineEntry.setPricebookId(line.getPricebookId());

                lineEntryList.add(lineEntry);
                System.out.println("Persist line entry object");
                em.persist(lineEntry);

                em.flush();
            }

            System.out.println("Create quotation");
            quotation.create(lineEntryList, dateIssued, "QN", client);
            System.out.println("Persist Quotation");
            em.persist(quotation);

            Collection<LineEntryEntity> list = quotation.getLineEntryList();
            for (Object o : list) {
                LineEntryEntity l = (LineEntryEntity) o;
                Long itemId = l.getItemId();
                int quantity = l.getQuantity();
                
                System.out.println("SOP : Get lead time");
                int days = getLeadTime(quotation.getId(), itemId, quantity, 3, 0, false);
                System.out.println("SOP : Lead Time is " + days);
                
                if (days > totalLeadTime) {
                    totalLeadTime = days;
                }
                
                l.setLeadTime(days);
                em.flush();
            }

            em.flush();
            
            System.out.println("Test :: Contact not null?");
            if (contactId != null) {
                System.out.println("Contact not null");
                ContactEntity contact = em.find(ContactEntity.class, contactId);
                quotation.setContact(contact);
            }
            
            quotation.setvalidUntil(validUntil);
            quotation.setDescription(description);
            quotation.setDocumentName(docName);
            quotation.setIndicativeLeadtime(totalLeadTime);
            quotation.setStatus(status);
            quotation.setPricingType(pricingType);
            em.flush();

            quotationId = quotation.getId();
            em.flush();
        }
        
        System.out.println("Result :"+quotationId);
        return quotationId;
    }

    public String editQuotation(Long id, Date dateIssued, Long clientId, Date validUntil,
                                int indicativeLeadTime, String description, 
                                String docName, String status) {
        
        System.out.println("Edit Quotation");
        String result = "";
        
        System.out.println("Find quotation");
        QuotationEntity quotation = em.find(QuotationEntity.class, id);

        if (quotation != null && quotation.getDeleteFlag().endsWith("N")) {
            System.out.println("Quotation found!");
            quotation.setDateIssued(dateIssued);
            quotation.setvalidUntil(validUntil);
            quotation.setIndicativeLeadtime(indicativeLeadTime);
            quotation.setDescription(description);
            quotation.setDocumentName(docName);
            quotation.setStatus(status);

            //annul reservations of products
            System.out.println("Check if status is edited to voided");
            if (status.equals("Voided")) {
                System.out.println("Status is voided, so annul reservations!");
                annulReservationsOnSalesOrder(quotation.getBackOrder().getId());
            }
            
            ClientEntity client = em.find(ClientEntity.class, clientId);
            if (client != null && client.getDeleteFlag().equals("N")) {
                quotation.setClient(client);
                em.flush();
            } else {
                System.out.println("Client not found.");                
            }
            
            em.flush();
            result = "Quotation edited";
            
        } else {
            result = "No such quotation";
        }
        
        System.out.println("Result :"+result);
        return result;
    }

    public String deleteQuotation(Long id) {

        System.out.println("Delete quotation");
        String result;

        System.out.println("Find quotation");
        QuotationEntity quotation = em.find(QuotationEntity.class, id);

        if (quotation != null && quotation.getDeleteFlag().equals("N")) {
            System.out.println("Quotation found");
            if (!quotation.getStatus().equals("Voided")) {
                //if status has not been voided before;
                System.out.println("Status before is not voided, annul reservation on quotation");
                if (quotation.getBackOrder() != null) {
                    annulReservationsOnSalesOrder(quotation.getBackOrder().getId());
                }
            }
            
            System.out.println("Set delete flag of quotation to Y");
            quotation.setDeleteFlag("Y");
            em.flush();

            System.out.println("Find line entry list");
            Collection<LineEntryEntity> lineEntryList = quotation.getLineEntryList();
            for (Object l : lineEntryList) {
                System.out.println("Line entry found, set delete flag to Y");
                LineEntryEntity lineEntry = (LineEntryEntity) l;
                lineEntry.setDeleteFlag("Y");
                em.flush();
            }
        
            result = "Quotation deleted";
        } else {
            System.out.println("Quotation not found");
            result = "No such quotation, deletion failed";
        }
        
        System.out.println("Result : "+result);
        return result;
    }

    public String updateLineEntry(Long id, int indicativeLeadTime, int amountShipped, int amountInvoiced) {
        
        System.out.println("Update line entry");
        String result;
        
        System.out.println("Find the corresponding line entry");
        LineEntryEntity lineEntry = em.find(LineEntryEntity.class, id);
        if (lineEntry != null && lineEntry.getDeleteFlag().equals("N")) {
            System.out.println("Line entry found");
            lineEntry.setLeadTime(indicativeLeadTime);
            em.flush();
            lineEntry.setAmountInvoiced(amountInvoiced);
            lineEntry.setAmountShipped(amountShipped);
            
            System.out.println("Check total invoiced and shipped");
            int total = amountInvoiced + amountShipped;
            if (total > lineEntry.getTotalLinePrice()) {
                System.out.println("Amount shipped and invoiced not match with total sales order!");
            } else {
                em.flush();
            }

            result = "Line entry updated";
        } else {
            result = "Update failed, no line Entry exist";
        }
        
        System.out.println("Result : "+result);
        return result;
    }

    public Long convertQuotationToPurchaseOrder(Long quotationId, Long billingId, Long shippingId,
            String description, Date dueDate, String docName, String shippingMethod, String shippingRule,
            String invoiceRule, String paymentMethod, String freightCostRule,
            String currency) {

        System.out.println("Convert quotation to purchase order");
        Long returnId = Long.parseLong("0");
        
        System.out.println("Find quotation");
        QuotationEntity quotation = em.find(QuotationEntity.class, quotationId);
        
        if (quotation != null && quotation.getDeleteFlag().equals("N")) {
            System.out.println("Quotation found.");
            ClientEntity client = quotation.getClient();
            Long clientId = client.getId();
            Collection<LineEntryEntity> lineEntryCollection = quotation.getLineEntryList();
            List<LineEntryEntity> lineEntryList = new ArrayList<LineEntryEntity>(lineEntryCollection);

            String pricingType = quotation.getPricingType();

            Long contactId;
            System.out.println("Test :: contact not null?");
            ContactEntity contact = quotation.getContact();
            if (contact != null) {
                System.out.println("Contact not null");
                contactId = contact.getId();
            } else {
                contactId = null;
            }

            System.out.println("Get date now");
            Calendar currentDate = Calendar.getInstance();
            SimpleDateFormat formatter = new SimpleDateFormat("dd/MM/yyyy");
            Date dateNow = currentDate.getTime();
     

            List<LineEntryState> lineEntryStateList = new ArrayList<LineEntryState>();
            for (Object o : lineEntryList) {
                LineEntryEntity line = (LineEntryEntity) o;
                Long itemId = line.getItemId();
                String itemName = line.getItemName();
                int quantity = line.getQuantity();
                double price = line.getPrice();
                LineEntryState les = new LineEntryState(itemId, itemName, quantity, price);
                les.setId(line.getId());
                les.setIndicativeLeadTime(line.getLeadTime());
                les.setBasePrice(line.getBasePrice());
                les.setAmountInvoiced(line.getAmountInvoiced());
                les.setAmountShipped(line.getAmountShipped());
                les.setTotalPrice(line.getTotalLinePrice());
                les.setPricebookId(line.getPricebookId());
                les.setPricingType(quotation.getPricingType());

                lineEntryStateList.add(les);
            }
            
            System.out.println("Calling add purchase order");
            Long poId = addPurchaseOrder(dateNow, clientId, contactId, lineEntryStateList, quotationId, billingId,
                    shippingId, description, dueDate, docName, shippingMethod, shippingRule,
                    invoiceRule, paymentMethod, freightCostRule, currency, pricingType);
            System.out.println("Purchase order created. PO id is : " + poId);
            
            System.out.println("Set status to converted");
            quotation.setStatus("Converted");
            quotation.setReferred(true);
            returnId = poId;
        }
        
        System.out.println("Return id is :"+returnId);
        return returnId;

    }

    public Long convertPurchaseOrderToSalesOrder(Long poId, String soName, String soDesc) {

        System.out.println("Convert Purchase Order to Sales order");
        Long returnId = Long.parseLong("0");
       
        System.out.println("Find purchase order");
        PurchaseOrderEntity po = em.find(PurchaseOrderEntity.class, poId);

        if (po != null && po.getDeleteFlag().equals("N")) {
            System.out.println("Purchase order found");
            ClientEntity client = po.getClient();
            Long clientId = client.getId();

            Collection<LineEntryEntity> lineEntryCollection = po.getLineEntryList();
            List<LineEntryEntity> lineEntryList = new ArrayList<LineEntryEntity>(lineEntryCollection);
            String description = po.getDescription();

            Long billingId = Long.parseLong("0");
            Long shippingId = Long.parseLong("0");
            if (po.getBillingAddress() != null) {
                billingId = po.getBillingAddress().getId();
            }
            if (po.getShippingAddress() != null) {
                shippingId = po.getShippingAddress().getId();
            }

            String shippingMethod = po.getShippingMethod();
            String shippingRule = po.getShippingRule();
            String invoiceRule = po.getInvoiceRule();
            String paymentMethod = po.getPaymentMethod();
            String freightCostRule = po.getFreightCostRule();
            String currency = po.getCurrency();
            Date dueDate = po.getDueDate();
            String pricingType = po.getPricingType();
            String docName = soName;
            
            System.out.println("Get date now");
            Calendar currentDate = Calendar.getInstance();
            SimpleDateFormat formatter = new SimpleDateFormat("dd/MM/yyyy");
            Date dateNow = currentDate.getTime();

            List<LineEntryState> lineEntryStateList = new ArrayList<LineEntryState>();
            for (Object o : lineEntryList) {
                LineEntryEntity line = (LineEntryEntity) o;
                Long itemId = line.getItemId();
                String itemName = line.getItemName();
                int quantity = line.getQuantity();
                double price = line.getPrice();
                LineEntryState les = new LineEntryState(itemId, itemName, quantity, price);
                les.setId(line.getId());
                les.setIndicativeLeadTime(line.getLeadTime());
                les.setBasePrice(line.getBasePrice());
                les.setAmountInvoiced(line.getAmountInvoiced());
                les.setAmountShipped(line.getAmountShipped());
                les.setTotalPrice(line.getTotalLinePrice());
                les.setPricebookId(line.getPricebookId());
                les.setPricingType(po.getPricingType());

                lineEntryStateList.add(les);
            }
            Long contactId;
            System.out.println("Test :: contact not null?");
            if (po.getContact() != null) {
                System.out.println("Contact not null");
                contactId = po.getContact().getId();
            } else {
                contactId = null;
            }


            System.out.println("Calling add sales order");
            Long soId = addSalesOrder(dateNow, clientId, contactId, lineEntryStateList, poId, billingId,
                    shippingId, soDesc, dueDate, docName, shippingMethod,
                    shippingRule, invoiceRule, paymentMethod, "Medium", freightCostRule, currency, pricingType);
            System.out.println("Sales order created. SO id is : " + soId);
            
            System.out.println("Setting purchase order status to converted");
            po.setStatus("Converted");
            po.setReferred(true);

            returnId = soId;
        }

        System.out.println("Return id : "+returnId);
        return returnId;
    }

    public Long convertPurchaseOrderToSalesOrder2(Long poId, String soName, String soDesc) {

        System.out.println("Convert Purchase Order to sales order");
        Long returnId = Long.parseLong("0");
        
        System.out.println("Find purchase order");
        PurchaseOrderEntity po = em.find(PurchaseOrderEntity.class, poId);

        if (po != null && po.getDeleteFlag().equals("N")) {

            System.out.println("Purchase order found");
            ClientEntity client = po.getClient();
            Long clientId = client.getId();

            Collection<LineEntryEntity> lineEntryCollection = po.getLineEntryList();
            List<LineEntryEntity> lineEntryList = new ArrayList<LineEntryEntity>(lineEntryCollection);
            String description = po.getDescription();

            Long billingId = Long.parseLong("0");
            Long shippingId = Long.parseLong("0");
            if (po.getBillingAddress() != null) {
                billingId = po.getBillingAddress().getId();
            }
            if (po.getShippingAddress() != null) {
                shippingId = po.getShippingAddress().getId();
            }

            String shippingMethod = po.getShippingMethod();
            String shippingRule = po.getShippingRule();
            String invoiceRule = po.getInvoiceRule();
            String paymentMethod = po.getPaymentMethod();
            String freightCostRule = po.getFreightCostRule();
            String currency = po.getCurrency();
            Date dueDate = po.getDueDate();
            String pricingType = po.getPricingType();
            String docName = soName;
            
            System.out.println("Get date now");
            Calendar currentDate = Calendar.getInstance();
            SimpleDateFormat formatter = new SimpleDateFormat("dd/MM/yyyy");
            Date dateNow = currentDate.getTime();

            List<LineEntryState> lineEntryStateList = new ArrayList<LineEntryState>();
            for (Object o : lineEntryList) {
                LineEntryEntity line = (LineEntryEntity) o;
                Long itemId = line.getItemId();
                String itemName = line.getItemName();
                int quantity = line.getQuantity();
                double price = line.getPrice();
                LineEntryState les = new LineEntryState(itemId, itemName, quantity, price);
                les.setId(line.getId());
                les.setIndicativeLeadTime(line.getLeadTime());
                les.setBasePrice(line.getBasePrice());
                les.setAmountInvoiced(line.getAmountInvoiced());
                les.setAmountShipped(line.getAmountShipped());
                les.setTotalPrice(line.getTotalLinePrice());
                les.setPricebookId(line.getPricebookId());
                les.setPricingType(po.getPricingType());

                lineEntryStateList.add(les);
            }
            Long contactId;
            System.out.println("Test :: contact not null?");
            if (po.getContact() != null) {
                System.out.println("Contact not null");
                contactId = po.getContact().getId();
            } else {
                contactId = null;
            }


            System.out.println("Calling sales order");
            Long soId = addSalesOrder2(dateNow, clientId, contactId, lineEntryStateList, poId, billingId,
                    shippingId, soDesc, dueDate, docName, shippingMethod,
                    shippingRule, invoiceRule, paymentMethod, "Medium", freightCostRule, currency, pricingType);
            System.out.println("Sales order created. SO id is : " + soId);
            
            System.out.println("Set purchase order to converted");
            po.setStatus("Converted");
            po.setReferred(true);

            returnId = soId;
        }


        return returnId;
    }

    public void addShippingGroup(Long doId, Long contactId, String shippingMethod, String shippingRule,
            String freightCostRule, Long billingId, Long shippingId,
            List<LineEntryState> le) {

        DeliveryOrderEntity doe = em.find(DeliveryOrderEntity.class, doId);
        DeliveryOrderEntity newDelivery = new DeliveryOrderEntity();
        SalesOrderEntity so = doe.getSalesOrder();
        if (doe != null) {
            System.out.println("Delivery order not null");
            Date now = doe.getDateIssued();
            Date due = doe.getDueDate();
            Date check = doe.getCheckBy();

            CustomerEntity cu = doe.getCustomer();
            double totalPrice = 0;
            double finalPrice = 0;

            List<LineEntryEntity> lineEntryList = new ArrayList<LineEntryEntity>();

            for (Object o : le) {

                LineEntryState line = (LineEntryState) o;
                System.out.println("Find product");
                ProductEntity product = em.find(ProductEntity.class, line.getItemId());
                String itemName = "";
                double basePrice = 0;
                if (product != null) {
                    System.out.println("If product not null");
                    itemName = product.getName();
                    basePrice = product.getBasePrice();
                }
                int quantity = line.getQuantity();
                System.out.println("quantity in the new ship group :" + quantity);
                double price = line.getPrice();
                Long itemId = line.getItemId();
                double oneItemPrice = quantity * price;

                LineEntryEntity lineEntry = new LineEntryEntity();
                System.out.println("Create line entry object");
                lineEntry.create(itemId, itemName, quantity, price, product);
                lineEntry.setTotalLinePrice(oneItemPrice);
                finalPrice = finalPrice + oneItemPrice;
                lineEntry.setPricebookId(line.getPricebookId());
                lineEntryList.add(lineEntry);
                System.out.println("Persist line entry object");
                em.persist(lineEntry);
                // lineEntry.setLeadTime(days);
                em.flush();
            }

            BillingAddressEntity ba = em.find(BillingAddressEntity.class, billingId);
            ShippingAddressEntity sa = em.find(ShippingAddressEntity.class, shippingId);

            ContactEntity contact = new ContactEntity();
            if (so.getContact() != null) {
                contact = so.getContact();
            } else {
                contact = null;
            }
            newDelivery.create(now, due, check, shippingMethod, shippingRule,
                    freightCostRule, lineEntryList, ba, sa, cu);

            em.persist(newDelivery);

            newDelivery.setSalesOrder(so);
            PickingOrderEntity poe = doe.getPickingOrderEntity();
            newDelivery.setContact(contact);
            newDelivery.setPaymentMethod(so.getPaymentMethod());
            newDelivery.setPricingType(so.getPricingType());
            newDelivery.setStatus("In Progress");
            newDelivery.setDeleteFlag("N");
            newDelivery.setDescription(so.getDescription());
            newDelivery.setDocumentName("New DO-ShipGroup for SO" + so.getId());
            newDelivery.setSalesOrder(so);
            newDelivery.setTotalPrice(finalPrice);
            so.getDeliveryOrderList().add(newDelivery);
            em.flush();
            Long doId1 = newDelivery.getId();

            System.out.println("Create picking order ");
            PickingOrderEntity pick1 = imm.createPickingOrder(doId1, poe.getPickingRoute(), "First-In First-Out",
                    poe.getIssueDate(), poe.getDueDate(),
                    poe.getCollectionWarehouseId(), 1);

            //PickingOrderEntity poe1 = em.find(PickingOrderEntity.class, pick1);
            //newDelivery.setPickingOrderEntity(poe1);
            // so.getDeliveryOrderList().add(newDelivery);
            // poe1.setEntries(poe1.getEntries());
            em.flush();

            //setting the quantity in delivery order and picking order
            List<LineEntryEntity> leList = doe.getLineEntryList();
            double grandTotal = 0;
            for (Object o : leList) {
                LineEntryEntity a = (LineEntryEntity) o;
                for (Object p : newDelivery.getLineEntryList()) {
                    LineEntryEntity b = (LineEntryEntity) p;
                    if (a.getItemId().equals(b.getItemId())) {
                        int qty = a.getQuantity();
                        int newQty = qty - b.getQuantity();
                        double total = a.getPrice() * newQty;
                        grandTotal = grandTotal + total;
                        a.setQuantity(newQty);
                        a.setTotalLinePrice(total);
                        em.flush();
                    }
                }

            }
            doe.setTotalPrice(grandTotal);


            for (Object o : pick1.getEntries()) {
                PickingOrderEntryEntity a = (PickingOrderEntryEntity) o;
                for (Object p : poe.getEntries()) {
                    PickingOrderEntryEntity b = (PickingOrderEntryEntity) p;
                    if (a.getProductId().equals(b.getProductId())) {
                        int qty = b.getRequestedQty();
                        int newQty = qty - a.getRequestedQty();
                        b.setRequestedQty(newQty);
                        em.flush();
                    }
                }

            }


        }
    }

    public void createDeliveryandPickingOrder(Long soId) {
        
        System.out.println("Create delivery and picking order");
        SalesOrderEntity so = em.find(SalesOrderEntity.class, soId);
        
        if (so != null) {
            
            System.out.println("Sales order found!");
            Calendar currentDate = Calendar.getInstance();
            SimpleDateFormat formatter = new SimpleDateFormat("dd/MM/yyyy");
            Date dateNow = currentDate.getTime();

            Calendar cal1 = Calendar.getInstance();
            cal1.setTime(dateNow);
            cal1.add(Calendar.DATE, 3);
            Date dateDueDO1 = cal1.getTime();

            Calendar cal2 = Calendar.getInstance();
            cal2.setTime(dateNow);
            cal2.add(Calendar.DATE, so.getleadTimeConfirmed());
            Date dateDueDO2 = cal2.getTime();

            Date checkBy1 = dateNow;

            Calendar cal3 = Calendar.getInstance();
            cal3.setTime(dateDueDO2);
            cal3.add(Calendar.DATE, -3);
            Date checkBy2 = cal3.getTime();

            
            int confirmedLeadTime = so.getleadTimeConfirmed();
            int indicativeLeadTime = so.getLeadTime();

            if (confirmedLeadTime > indicativeLeadTime) {
                
                System.out.println("Confirmed Lead time more than indicative lead time.");
                System.out.println("Create two delivery and picking orders.");
                Collection<LineEntryEntity> leCol = so.getLineEntryList();
                List<LineEntryEntity> doList1 = new ArrayList<LineEntryEntity>();
                List<LineEntryEntity> doList2 = new ArrayList<LineEntryEntity>();
                double totalPrice1 = 0;
                double totalPrice2 = 0;
                
                for (Object o : leCol) {
                    
                    LineEntryEntity line = (LineEntryEntity) o;
                    
                    System.out.println("Find product");
                    ProductEntity product = em.find(ProductEntity.class, line.getItemId());

                    LineEntryEntity doLine1 = new LineEntryEntity();
                    LineEntryEntity doLine2 = new LineEntryEntity();
                    Long itemId = line.getItemId();
                    String itemName = line.getItemName();
                    
                
                    int immediateQty = line.getAmountCurrentlyAvailable();
                    System.out.println("Immediate Qty : "+immediateQty);
                    int qtyLeft = line.getQuantity() - immediateQty;
                    System.out.println("Quantity left : "+qtyLeft);
                    
                    int leadTime = line.getLeadTime();
                    System.out.println("Get lead time is : " + line.getLeadTime());
                    
                    double basePrice = line.getBasePrice();
                    double price = line.getPrice();

                    double linePrice1 = immediateQty * price;
                    double linePrice2 = qtyLeft * price;

                    totalPrice1 = totalPrice1 + linePrice1;
                    totalPrice2 = totalPrice2 + linePrice2;

                    doLine1.create(itemId, itemName, immediateQty, basePrice, price, leadTime, product);
                    em.persist(doLine1);

                    doLine1.setTotalLinePrice(linePrice1);
                    em.flush();

                    doLine2.create(itemId, itemName, qtyLeft, basePrice, price, leadTime, product);
                    em.persist(doLine2);

                    doLine2.setTotalLinePrice(linePrice2);
                    em.flush();

                    doList1.add(doLine1);
                    em.flush();
                    doList2.add(doLine2);
                    em.flush();
                }

                ContactEntity contact = new ContactEntity();
                System.out.println("Test :: contact not null");
                if (so.getContact() != null) {
                    contact = so.getContact();
                } else {
                    contact = null;
                }

                CustomerEntity cu = (CustomerEntity) so.getClient();

                System.out.println("Create delivery order 1");
                DeliveryOrderEntity doe1 = new DeliveryOrderEntity();
                doe1.create(dateNow, dateDueDO1, checkBy1, so.getShippingMethod(),
                        so.getShippingRule(), so.getFreightCostRule(), doList1, so.getBillingAddress(),
                        so.getShippingAddress(), cu);
                System.out.println("Persist delivery order 1");
                em.persist(doe1);
                doe1.setContact(contact);
                doe1.setPaymentMethod(so.getPaymentMethod());
                doe1.setPricingType(so.getPricingType());
                doe1.setStatus("In Progress");
                doe1.setDeleteFlag("N");
                doe1.setDescription(so.getDescription());
                doe1.setDocumentName("DO1 for SO" + so.getId());
                doe1.setSalesOrder(so);
                doe1.setTotalPrice(totalPrice1);
                so.getDeliveryOrderList().add(doe1);
                em.flush();
                Long doId1 = doe1.getId();

                System.out.println("Create delivery order 2");
                DeliveryOrderEntity doe2 = new DeliveryOrderEntity();
                doe2.create(dateNow, dateDueDO2, checkBy2, so.getShippingMethod(),
                        so.getShippingRule(), so.getFreightCostRule(), doList2, so.getBillingAddress(),
                        so.getShippingAddress(), cu);
                System.out.println("Persist delivery order 2");
                em.persist(doe2);
                doe2.setContact(contact);
                doe2.setPaymentMethod(so.getPaymentMethod());
                doe2.setPricingType(so.getPricingType());
                doe2.setStatus("In Progress");
                doe2.setDeleteFlag("N");
                doe2.setDescription(so.getDescription());
                doe2.setDocumentName("DO2 for SO" + so.getId());
                doe2.setSalesOrder(so);
                doe2.setTotalPrice(totalPrice2);
                so.getDeliveryOrderList().add(doe2);
                em.flush();
                Long doId2 = doe2.getId();

                List<WarehouseState> wList = iib.viewWarehouse();
                Long warehouseId = wList.get(0).getId();

                System.out.println("Create picking order 1");
                PickingOrderEntity pick1 = imm.createPickingOrder(doId1, "Route 1", "First-In First-Out", dateNow, dateDueDO1,
                        warehouseId, 1);
                
                List<PickingOrderEntryEntity> pick1Entries = new ArrayList();
                pick1Entries = (List<PickingOrderEntryEntity>) pick1.getEntries();
                
                for (PickingOrderEntryEntity p1e : pick1Entries) {
                    if (!p1e.getReservationType().equals("INV")) {
                        imm.removePickingOrderEntryFromPickingList(pick1.getId(), p1e.getId());
                    }
                }
                
                System.out.println("Create picking order 2");
                PickingOrderEntity pick2 = imm.createPickingOrder(doId2, "Route 1", "First-In First-Out", dateNow, dateDueDO2,
                        warehouseId, 2);

                //    PickingOrderEntity poe1 = em.find(PickingOrderEntity.class, pick1.getId());
                //   doe1.setPickingOrderEntity(pick1);
                // em.flush();
                //   PickingOrderEntity poe2 = em.find(PickingOrderEntity.class, pick2);
                //  doe2.setPickingOrderEntity(pick2);
                //  em.flush();

            } else {
                System.out.println("Confirmed lead time not more than indicative lead time");
                Collection<LineEntryEntity> leCol = so.getLineEntryList();
                List<LineEntryEntity> doList = new ArrayList<LineEntryEntity>();

                double totalPrice = 0;

                for (Object o : leCol) {
                   
                    LineEntryEntity line = (LineEntryEntity) o;
                    System.out.println("Find product");
                    ProductEntity product = em.find(ProductEntity.class, line.getItemId());

                    LineEntryEntity doLine = new LineEntryEntity();

                    Long itemId = line.getItemId();
                    String itemName = line.getItemName();
                    int qty = line.getQuantity();

                    double basePrice = line.getBasePrice();
                    double price = line.getPrice();
                    double linePrice = qty * price;

                    totalPrice = totalPrice + linePrice;

                    int leadTime = line.getLeadTime();

                    doLine.create(itemId, itemName, qty, basePrice, price, product);
                    em.persist(doLine);
                    doLine.setTotalLinePrice(linePrice);
                    em.flush();

                    doList.add(doLine);
                    em.flush();

                }

                ContactEntity contact = new ContactEntity();
                System.out.println("Test :: contact not null?");
                if (so.getContact() != null) {
                    System.out.println("Contact not null");
                    contact = so.getContact();
                } else {
                    contact = null;
                }

                CustomerEntity cu = (CustomerEntity) so.getClient();

                System.out.println("Create delivery order");
                DeliveryOrderEntity doe = new DeliveryOrderEntity();
                doe.create(dateNow, dateDueDO1, checkBy1, so.getShippingMethod(),
                        so.getShippingRule(), so.getFreightCostRule(), doList, so.getBillingAddress(),
                        so.getShippingAddress(), cu);
                em.persist(doe);
                doe.setContact(contact);
                doe.setPaymentMethod(so.getPaymentMethod());
                doe.setPricingType(so.getPricingType());
                doe.setStatus("In Progress");
                doe.setDeleteFlag("N");
                doe.setDescription(so.getDescription());
                doe.setDocumentName("DO1 for SO" + so.getId());
                doe.setSalesOrder(so);
                doe.setTotalPrice(totalPrice);
                so.getDeliveryOrderList().add(doe);
                em.flush();
                Long doId1 = doe.getId();

                List<WarehouseState> wList = iib.viewWarehouse();
                Long warehouseId = wList.get(0).getId();

                System.out.println("Create picking order");
                PickingOrderEntity pick1 = imm.createPickingOrder(doId1, "Route 1", "First-In First-Out", dateNow, dateDueDO1,
                        warehouseId, 1);

                //PickingOrderEntity poe1 = em.find(PickingOrderEntity.class, pick1);
                //doe.setPickingOrderEntity(poe1);
                em.flush();

            }
        }
    }
    
    public String approvePurchaseOrder(Long id) {
        
        String result;
        System.out.println("approvePurchaseOrder");
        PurchaseOrderEntity po = em.find(PurchaseOrderEntity.class, id);
        
        if (po != null && po.getDeleteFlag().equals("N")) {
            po.setStatus("Validated");
            em.flush();
            
            int leadTime = po.getQuotation().getIndicativeLeadtime();//become lead time in sales order when approved
            Date dateIssued = po.getDateIssued();
            ClientEntity client = po.getClient();
            Collection<LineEntryEntity> lineEntryCollection = po.getLineEntryList();
            List<LineEntryEntity> lineEntryList = new ArrayList<LineEntryEntity>(lineEntryCollection);
            
            System.out.println("Sales Order automatically created");
            
            SalesOrderEntity so = new SalesOrderEntity();
            so.create(lineEntryCollection, dateIssued, "SO", client);
            em.persist(so);
            so.setStatus("In Progress");
            so.setPurchaseOrder(po);
            so.setATPCheckStatus("In Progress");
            so.setCreditCheckStatus("In Progress");
            so.setBillingAddress(po.getBillingAddress());
            so.setShippingAddress(po.getShippingAddress());
            so.setLeadTime(po.getQuotation().getIndicativeLeadtime());
            
            so.setDescription(po.getDescription());
            em.flush();
   
            result = "PO approved";
            
        } else {
            System.out.println("Purchase Order not found.");
            result = "PO not found";
        }
        
        return result;
    }

    public Long addPurchaseOrder(Date dateIssued, Long clientId, Long contactId, List<LineEntryState> products,
            Long quotationId, Long billingId, Long shippingId, String description,
            Date dueDate, String docName, String shippingMethod, String shippingRule,
            String invoiceRule, String paymentMethod, String freightCostRule,
            String currency, String pricingType) {
        
        System.out.println("Add purchase order");
        Long poId;


        String status = "In Progress";
        
        System.out.println("Find client and quotation");
        ClientEntity client = em.find(ClientEntity.class, clientId);
        QuotationEntity quotation = em.find(QuotationEntity.class, quotationId);

        if (client != null && client.getDeleteFlag().equals("N")
                && quotation != null && quotation.getDeleteFlag().equals("N")) {
            
            System.out.println("Client and quotation found");
            PurchaseOrderEntity po = new PurchaseOrderEntity();
            Collection<LineEntryEntity> lineEntryList = new ArrayList<LineEntryEntity>();
            if (contactId != null) {
                ContactEntity contact = em.find(ContactEntity.class, contactId);
                po.setContact(contact);
            }
         
            if (!products.isEmpty()) {
                System.out.println("Test :: Products not null");
            }
            
            for (Object o : products) {
                
                LineEntryState line = (LineEntryState) o;
                
                System.out.println("Find product");
                ProductEntity product = em.find(ProductEntity.class, line.getItemId());
                
                String itemName = "";
                double basePrice = 0;
                if (product != null) {
                    System.out.println("If product not null");
                    itemName = product.getName();
                    basePrice = product.getBasePrice();
                }
                
                int quantity = line.getQuantity();
                double price = line.getPrice();
                Long itemId = line.getItemId();

                LineEntryEntity lineEntry = new LineEntryEntity();
                System.out.println("Create line entry object");
                lineEntry.create(itemId, itemName, quantity, basePrice, price, product);
                lineEntry.setTotalLinePrice(line.getTotalPrice());
                lineEntry.setPricebookId(line.getPricebookId());
                lineEntry.setLeadTime(line.getIndicativeLeadTime());
                lineEntryList.add(lineEntry);
                System.out.println("Persist line entry object");
                em.persist(lineEntry);

            }
            
            System.out.println("Create purchase order");
            po.create(lineEntryList, dateIssued, "PO", client);
            System.out.println("Persist Purchase Order");
            em.persist(po);

            
            if (paymentMethod.equals("Cash")) {
                System.out.println("Check if payment method equals cash");
                po.setCashInAdvanced(true);
            }
            po.setStatus(status);
            po.setQuotation(quotation);
            po.setDescription(description);

            BillingAddressEntity ba = new BillingAddressEntity();
            ShippingAddressEntity sa = new ShippingAddressEntity();
            if (billingId != 0) {
                ba = em.find(BillingAddressEntity.class, billingId);
                if (ba != null) {
                    System.out.println("Billing address found, set billing address for PO");
                    po.setBillingAddress(ba);
                }
            }
            if (shippingId != 0) {
                sa = em.find(ShippingAddressEntity.class, shippingId);
                if (sa != null) {
                    System.out.println("Shipping address found, set shipping address for PO");
                    po.setShippingAddress(sa);
                }
            }

            po.setDocumentName(docName);
            po.setDueDate(dueDate);
            po.setDeleteFlag("N");
            po.setCurrency(currency);
            po.setShippingMethod(shippingMethod);
            po.setShippingRule(shippingRule);
            po.setInvoiceRule(invoiceRule);
            po.setPaymentMethod(paymentMethod);
            po.setPricingType(pricingType);
            po.setFreightCostRule(freightCostRule);
            po.setLeadTime(quotation.getIndicativeLeadtime());
            em.flush();
            
            System.out.println("Set quotation to referred and approved");
            quotation.setReferred(true);
            quotation.setStatus("Approved");
            em.flush();

            CustomerEntity customer = new CustomerEntity();
            if (client.getClientType().equals("SL")) {
                System.out.println("Sales lead orders, convert to customer");
                
                System.out.println("Sales Lead Id is " + clientId);
                System.out.println("Convert sales lead to customer");
                Long customerId = smb.convertSalesLead(clientId);
                System.out.println("Customer ID is " + customerId);
                
                if (customerId == 1 || customerId == 0 || customerId == 2) {
                    SalesLeadEntity sl = em.find(SalesLeadEntity.class, clientId);
                    String companyRegId = sl.getCompanyRegId();
                    Query q = em.createQuery("Select a from CustomerEntity a where a.companyRegId=:companyRegId").setParameter("companyRegId", companyRegId);
                    customer = (CustomerEntity) q.getSingleResult();
                } else {
                    customer = em.find(CustomerEntity.class, customerId);
                }

                po.setClient(customer);
                em.flush();
            }

            poId = po.getId();
        } else {
            System.out.println("Client not found.");
            String zero = "0";
            poId = Long.parseLong(zero);
        }

        System.out.println("Return id "+poId);
        return poId;
    }

    public String deletePurchaseOrder(Long id) {
        
        System.out.println("Delete purchase order");
        String result;
        
        PurchaseOrderEntity po = em.find(PurchaseOrderEntity.class, id);

        if (po != null) {
            
            po.setDeleteFlag("Y");
            em.flush();

            System.out.println("Find line entry list");
            Collection<LineEntryEntity> lineEntryList = po.getLineEntryList();
            for (Object l : lineEntryList) {
                System.out.println("Line entry found");
                LineEntryEntity lineEntry = (LineEntryEntity) l;
                lineEntry.setDeleteFlag("Y");
                em.flush();
            }

            result = "PO deleted";
        } else {
            System.out.println("Purchase Order not found.");
            result = "Deletion failed, no such PO";
        }
        em.flush();
        return result;
    }

    public String updatePurchaseOrderStatus(Long id, String status) {
        
        System.out.println("Update purchase order status");
        String result;     

        PurchaseOrderEntity po = em.find(PurchaseOrderEntity.class, id);
        if (po != null && po.getDeleteFlag().equals("N")) {
            po.setStatus(status);
            em.flush();
            result = "PO status updated";
        } else {
            System.out.println("Purchase Order not found.");
            result = "PO not found, update failed";
        }
        System.out.println("Result is: "+result);
        return result;
    }

    public String editPurchaseOrder(Long id, Date dateIssued, Long clientId, Long contactId, Long quotationId, String status,
            String description,
            Date dueDate, String docName, String shippingMethod, String shippingRule,
            String invoiceRule, String paymentMethod, String freightCostRule,
            String currency, Long billingId, Long shippingId) {
        
        System.out.println("Edit purchase order");
        String result = "";
        
        PurchaseOrderEntity po = em.find(PurchaseOrderEntity.class, id);

        if (po != null && po.getDeleteFlag().equals("N")) {

            BillingAddressEntity ba = new BillingAddressEntity();
            ShippingAddressEntity sa = new ShippingAddressEntity();
            if (billingId != 0) {
                ba = em.find(BillingAddressEntity.class, billingId);
                if (ba != null) {
                    po.setBillingAddress(ba);
                }
            }
            if (shippingId != 0) {
                sa = em.find(ShippingAddressEntity.class, shippingId);
                if (sa != null) {
                    po.setShippingAddress(sa);
                }
            }

            po.setDateIssued(dateIssued);
            po.setStatus(status);
            po.setDescription(description);
            po.setDueDate(dueDate);
            po.setDocumentName(docName);
            po.setCurrency(currency);
            po.setShippingMethod(shippingMethod);
            po.setShippingRule(shippingRule);
            po.setInvoiceRule(invoiceRule);
            po.setPaymentMethod(paymentMethod);
            
            if (paymentMethod.equals("Cash")) {
                System.out.println("If payment method is cash");
                po.setCashInAdvanced(true);
            } else {
                po.setCashInAdvanced(false);
            }
            po.setFreightCostRule(freightCostRule);

            if (contactId != null) {
                ContactEntity contact = em.find(ContactEntity.class, contactId);
                po.setContact(contact);
            }

            ClientEntity client = em.find(ClientEntity.class, clientId);
            if (client != null && client.getDeleteFlag().equals("N")) {
                po.setClient(client);
                em.flush();
                result = "Client added.";
            } else {
                System.out.println("Client not found");
                result = "Client not found.";
            }

            QuotationEntity quotation = em.find(QuotationEntity.class, quotationId);
            if (quotation != null && quotation.getDeleteFlag().equals("N")) {
                po.setQuotation(quotation);
                em.flush();
                result = result + "Quotation added.";
            } else {
                System.out.println("Quotation not found");
                result = result + "Quotation not found.";
            }
            em.flush();
            result = result + " PO found.";
        } else {
            System.out.println("Purchase Order not found.");
            result = "PO not found";
        }
        
        System.out.println("Result : "+result);
        return result;
    }

    public Long addSalesOrder(Date dateIssued, Long clientId, Long contactId, List<LineEntryState> products, Long poId,
            Long billingId, Long shippingId, String description,
            Date dueDate, String docName, String shippingMethod, String shippingRule,
            String invoiceRule, String paymentMethod, String priority, String freightCostRule,
            String currency, String pricingType) {
        
        System.out.println("addSalesOrder");
        Long soId;

        String status = "In Progress";
        String ATPCheckStatus = "In Progress";
        String creditCheckStatus = "In Progress";
        
        double finalPrice = 0;
        
        ClientEntity client = em.find(ClientEntity.class, clientId);
        PurchaseOrderEntity po = em.find(PurchaseOrderEntity.class, poId);

        if (client != null && client.getDeleteFlag().equals("N")
                && po != null && po.getDeleteFlag().equals("N")) {
            
            System.out.println("Client and purchase order found");
            SalesOrderEntity so = new SalesOrderEntity();
            Collection<LineEntryEntity> lineEntryList = new ArrayList<LineEntryEntity>();

            System.out.println("Before creating a new sales order, create quotation");
            QuotationEntity qo = po.getQuotation();
            //withdraw reservation in quotation
            annulReservationsOnSalesOrder(qo.getBackOrder().getId());

            System.out.println("Test :: contact not null?");
            if (contactId != null) {
                System.out.println("Contact not null");
                ContactEntity contact = em.find(ContactEntity.class, contactId);
                so.setContact(contact);
            }
           
            if (!products.isEmpty()) {
                System.out.println("Line entry state not null");
            }
           
            int totalLeadTime = 0;
            double totalPrice = 0;
            
            for (Object o : products) {
                LineEntryState line = (LineEntryState) o;
                System.out.println("Find product");
                ProductEntity product = em.find(ProductEntity.class, line.getItemId());
                
                String itemName = "";
                double basePrice = 0;
                if (product != null) {
                    System.out.println("If product not null, get item name and base price");
                    itemName = product.getName();
                    basePrice = product.getBasePrice();
                }
                
                int quantity = line.getQuantity();
                double price = line.getPrice();
                Long itemId = line.getItemId();
                double oneItemPrice = quantity * price;
                totalPrice = totalPrice + oneItemPrice;
                
                LineEntryEntity lineEntry = new LineEntryEntity();
                System.out.println("Create line entry object");
                lineEntry.create(itemId, itemName, quantity, price, product);
                lineEntry.setTotalLinePrice(line.getTotalPrice());
                finalPrice = finalPrice + line.getTotalPrice();
                lineEntry.setPricebookId(line.getPricebookId());
                lineEntryList.add(lineEntry);
                System.out.println("Persist line entry object");
                em.persist(lineEntry);
                em.flush();

            }
            
            System.out.println("Create sales order");
            so.create(lineEntryList, dateIssued, "SO", client);
            System.out.println("Persist Sales Order");
            em.persist(so);

            Long salesOrderId = so.getId();
            Collection<LineEntryEntity> list = so.getLineEntryList();
            for (Object o : list) {
                LineEntryEntity l = (LineEntryEntity) o;
                Long itemId = l.getItemId();
                int quantity = l.getQuantity();
                System.out.println("Get lead time");
                ATPCheckState atpResult = getLeadTimeForSO(so.getId(), itemId, quantity, 3, po.getLeadTime(), true);
                int days = atpResult.getLeadTime();
                if (days > totalLeadTime) {
                    totalLeadTime = days;
                }
                l.setLeadTime(days);
                em.flush();
                int currentAvailableQty = atpResult.getImmediateInHandQty();
                l.setAmountCurrentlyAvailable(currentAvailableQty);            
                em.flush();
            }


            em.flush();

            if (paymentMethod.equals("Cash")) {
                so.setCashInAdvanced(true);
                System.out.println("Cash In Advance payment, notify finance department!");
                this.informCashInAdvancePayment(salesOrderId, clientId);
            }
            
            so.setStatus(status);
            so.setPurchaseOrder(po);
            so.setCreditCheckStatus(creditCheckStatus);

            BillingAddressEntity ba = new BillingAddressEntity();
            ShippingAddressEntity sa = new ShippingAddressEntity();
            if (billingId != 0) {
                ba = em.find(BillingAddressEntity.class, billingId);
                if (ba != null) {
                    so.setBillingAddress(ba);
                }
            }
            if (shippingId != 0) {
                sa = em.find(ShippingAddressEntity.class, shippingId);
                if (sa != null) {
                    so.setShippingAddress(sa);
                }
            }
            so.setDocumentName(docName);
            so.setDueDate(dueDate);
            so.setCurrency(currency);
            so.setShippingMethod(shippingMethod);
            so.setShippingRule(shippingRule);
            so.setInvoiceRule(invoiceRule);
            so.setPaymentMethod(paymentMethod);
            so.setPriority(priority);
            so.setPricingType(pricingType);
            System.out.println("FINAL PRICE : " + finalPrice);
            so.setTotalPrice(finalPrice);
            System.out.println("TOTAL PRICE " + so.getTotalPrice());
            so.setFreightCostRule(freightCostRule);

            em.flush();
            po.setReferred(true);
            po.setStatus("Validated");
            em.flush();
            
            int indicativeLeadTime = so.getPurchaseOrder().getQuotation().getIndicativeLeadtime();
            System.out.println("Total Lead Time " + totalLeadTime);
            System.out.println("Indicative Lead Time " + indicativeLeadTime);
            if (totalLeadTime <= indicativeLeadTime) {
                ATPCheckStatus = "Available";
                if (creditCheckStatus.equals("In Progress")) {
                    status = "In Progress";
                } else if (creditCheckStatus.equals("Rejected")) {
                    status = "Rejected";
                }
            
            } else {
                ATPCheckStatus = "Not Available";
                status = "On Hold";
            }
            
            System.out.println("ATP CHECK STATUS : "+ATPCheckStatus+" Status is : "+status);
            so.setStatus(status);
            so.setATPCheckStatus(ATPCheckStatus);
            so.setLeadTime(indicativeLeadTime);
            so.setleadTimeConfirmed(totalLeadTime);
            System.out.println("Description : " + description);
            so.setDescription(description);
            em.flush();
            soId = so.getId();

            System.out.println("Generate Email for Credit Check!");
            requestForCreditCheck(clientId, soId);

        } else {
            System.out.println("Client not found.");
            String zero = "0";
            soId = Long.parseLong(zero);
        }

        System.out.println("Return id :"+soId);
        return soId;
    }

    //for J-Unit testing purpose
    public Long addSalesOrder2(Date dateIssued, Long clientId, Long contactId, List<LineEntryState> products, Long poId,
            Long billingId, Long shippingId, String description,
            Date dueDate, String docName, String shippingMethod, String shippingRule,
            String invoiceRule, String paymentMethod, String priority, String freightCostRule,
            String currency, String pricingType) {
        Long soId;

        System.out.println("addSalesOrder");

        String status = "In Progress";
        String ATPCheckStatus = "In Progress";
        String creditCheckStatus = "In Progress";
        double finalPrice = 0;

        ClientEntity client = em.find(ClientEntity.class, clientId);
        PurchaseOrderEntity po = em.find(PurchaseOrderEntity.class, poId);

        if (client != null && client.getDeleteFlag().equals("N")
                && po != null && po.getDeleteFlag().equals("N")) {
            System.out.println("Client and purchase order found");
            SalesOrderEntity so = new SalesOrderEntity();
            Collection<LineEntryEntity> lineEntryList = new ArrayList<LineEntryEntity>();

            QuotationEntity qo = po.getQuotation();
            //withdraw reservation in quotation
            annulReservationsOnSalesOrder(qo.getBackOrder().getId());

            if (contactId != null) {
                ContactEntity contact = em.find(ContactEntity.class, contactId);
                so.setContact(contact);
            }
          
            if (!products.isEmpty()) {
                System.out.println("Line entry state not null");
            }
        
            int totalLeadTime = 0;
            double totalPrice = 0;
            
            for (Object o : products) {
                LineEntryState line = (LineEntryState) o;
                System.out.println("Find product");
                ProductEntity product = em.find(ProductEntity.class, line.getItemId());
                String itemName = "";
                double basePrice = 0;
                if (product != null) {
                    System.out.println("If product not null");
                    itemName = product.getName();
                    basePrice = product.getBasePrice();
                }
                int quantity = line.getQuantity();
                double price = line.getPrice();
                Long itemId = line.getItemId();
                double oneItemPrice = quantity * price;
                totalPrice = totalPrice + oneItemPrice;
                
                LineEntryEntity lineEntry = new LineEntryEntity();
                System.out.println("Create line entry object");
                lineEntry.create(itemId, itemName, quantity, price, product);
                lineEntry.setTotalLinePrice(line.getTotalPrice());
                finalPrice = finalPrice + line.getTotalPrice();
                lineEntry.setPricebookId(line.getPricebookId());
                lineEntryList.add(lineEntry);
                System.out.println("Persist line entry object");
                em.persist(lineEntry);
                em.flush();
            }
            
            System.out.println("Create sales order");
            so.create(lineEntryList, dateIssued, "SO", client);
            System.out.println("Persist Sales Order");
            em.persist(so);

            Long salesOrderId = so.getId();
            Collection<LineEntryEntity> list = so.getLineEntryList();
            for (Object o : list) {
                LineEntryEntity l = (LineEntryEntity) o;
                Long itemId = l.getItemId();
                int quantity = l.getQuantity();
                ATPCheckState atpResult = getLeadTimeForSO(so.getId(), itemId, quantity, 3, po.getLeadTime(), true);
                int days = atpResult.getLeadTime();
                if (days > totalLeadTime) {
                    totalLeadTime = days;
                }
                l.setLeadTime(days);
                em.flush();
                int currentAvailableQty = atpResult.getImmediateInHandQty();
                l.setAmountCurrentlyAvailable(currentAvailableQty);               
                em.flush();
            }

            em.flush();

            if (paymentMethod.equals("Cash")) {
                so.setCashInAdvanced(true);
                System.out.println("Cash In Advance payment, notify finance department!");
                //this.informCashInAdvancePayment(salesOrderId, clientId);
            }
            so.setStatus(status);

            so.setPurchaseOrder(po);
            so.setCreditCheckStatus(creditCheckStatus);

            BillingAddressEntity ba = new BillingAddressEntity();
            ShippingAddressEntity sa = new ShippingAddressEntity();
            if (billingId != 0) {
                ba = em.find(BillingAddressEntity.class, billingId);
                if (ba != null) {
                    so.setBillingAddress(ba);
                }
            }
            if (shippingId != 0) {
                sa = em.find(ShippingAddressEntity.class, shippingId);
                if (sa != null) {
                    so.setShippingAddress(sa);
                }
            }
            so.setDocumentName(docName);
            so.setDueDate(dueDate);
            so.setCurrency(currency);
            so.setShippingMethod(shippingMethod);
            so.setShippingRule(shippingRule);
            so.setInvoiceRule(invoiceRule);
            so.setPaymentMethod(paymentMethod);
            so.setPriority(priority);
            so.setPricingType(pricingType);
            System.out.println("FINAL PRICE : " + finalPrice);
            so.setTotalPrice(finalPrice);
            System.out.println("TOTAL PRICE " + so.getTotalPrice());
            so.setFreightCostRule(freightCostRule);

            em.flush();
            po.setReferred(true);
            po.setStatus("Validated");
            em.flush();
            int indicativeLeadTime = so.getPurchaseOrder().getQuotation().getIndicativeLeadtime();
            System.out.println("Total Lead Time " + totalLeadTime);
            System.out.println("Indicative Lead Time " + indicativeLeadTime);
            if (totalLeadTime <= indicativeLeadTime) {
                ATPCheckStatus = "Available";
                if (creditCheckStatus.equals("In Progress")) {
                    status = "In Progress";
                } else if (creditCheckStatus.equals("Rejected")) {
                    status = "Rejected";
                }

            } else {
                ATPCheckStatus = "Not Available";
                status = "On Hold";
            }
            so.setStatus(status);
            so.setATPCheckStatus(ATPCheckStatus);
            so.setLeadTime(indicativeLeadTime);
            so.setleadTimeConfirmed(totalLeadTime);
            System.out.println("Description : " + description);
            so.setDescription(description);
            em.flush();
            soId = so.getId();

            System.out.println("Generate Email for Credit Check!");
            //requestForCreditCheck(clientId, soId);

        } else {
            System.out.println("Client not found.");
            String zero = "0";
            soId = Long.parseLong(zero);
        }
        
        System.out.println("Return is :"+soId);
        return soId;
    }

    public void requestRefund(Long customerId, Long salesOrderId) {
        
        pbr.createRefund(customerId, salesOrderId);
        System.out.println("Request for Refund");
        System.out.println("Generate email for Finance Executive");

        String title = "Request for Refund";
        String body = "\n" + "\n" + "Automated message from SALES DEPARTMENT to FINANCE DEPARTMENT" + "\n" + "\n"
                + "Request for refund for the following sales order: " + "\n"
                + "=========================" + "\n"
                + "Sales Order ID      : " + salesOrderId + "\n"
                + "Client ID           : " + customerId + "\n"
                + "=========================" + "\n" + "\n" + "\n"
                + "Sales Department" + "\n"
                + "Merlion Pte Ltd";

        System.out.println("Sending message");
        mmb.addMessage("Finance Executive", title, body);
        mmb.addMessage("Finance Manager", title, body);
    }

    public void requestForInvoice(Long customerId, Long salesOrderId) {

        System.out.println("Request for Invoice");
        System.out.println("Generate email for Finance Executive");

        String title = "Request for Invoice";
        String body = "\n" + "\n" + "Automated message from SALES DEPARTMENT to FINANCE DEPARTMENT" + "\n" + "\n"
                + "Request to invoice the following sales order: " + "\n"
                + "=========================" + "\n"
                + "Sales Order ID      : " + salesOrderId + "\n"
                + "Client ID           : " + customerId + "\n"
                + "=========================" + "\n" + "\n" + "\n"
                + "Sales Department" + "\n"
                + "Merlion Pte Ltd";

        System.out.println("Sending message");
        mmb.addMessage("Finance Executive", title, body);
        mmb.addMessage("Finance Manager", title, body);
    }

    public void requestForCreditCheck(Long customerId, Long salesOrderId) {

        System.out.println("Request for Credit Check");
        System.out.println("Generate email for Finance Executive");

        String title = "Request for Credit Check";
        String body = "\n" + "\n" + "Automated message from SALES DEPARTMENT to FINANCE DEPARTMENT" + "\n" + "\n"
                + "Request to perform credit check for the following sales order: " + "\n"
                + "=========================" + "\n"
                + "Sales Order ID      : " + salesOrderId + "\n"
                + "Client ID           : " + customerId + "\n"
                + "=========================" + "\n" + "\n" + "\n"
                + "Sales Department" + "\n"
                + "Merlion Pte Ltd";

        System.out.println("Sending message");
        mmb.addMessage("Finance Executive", title, body);
        mmb.addMessage("Finance Manager", title, body);

    }

    public void informCashInAdvancePayment(Long customerId, Long salesOrderId) {
        
        System.out.println("Inform Cash in Advance Payment");
        System.out.println("Generate email for Finance Executive");

        String title = "Notification of Cash in Advance Payment";
        String body = "\n" + "\n" + "Automated message from SALES DEPARTMENT to FINANCE DEPARTMENT" + "\n" + "\n"
                + "Notification of Cash In Advance payment for the following sales order: " + "\n"
                + "==================================" + "\n"
                + "Sales Order ID      : " + salesOrderId + "\n"
                + "Client ID           : " + customerId + "\n"
                + "==================================" + "\n" + "\n" + "\n"
                + "Sales Department" + "\n"
                + "Merlion Pte Ltd";

        System.out.println("Sending message");
        mmb.addMessage("Finance Executive", title, body);
        mmb.addMessage("Finance Manager", title, body);

    }

    public void editSalesOrder(Long id, Date dateIssued, Long clientId, Long contactId, Long poId, String status,
            String ATPCheckStatus, String creditCheckStatus,
            String description,
            Date dueDate, String docName, String shippingMethod, String shippingRule,
            String invoiceRule, String paymentMethod, String priority, String freightCostRule,
            String currency, Long billingId, Long shippingId) {
        
        System.out.println("Edit sales order");
        String result;
        
        SalesOrderEntity soe = em.find(SalesOrderEntity.class, id);

        if (soe != null && soe.getDeleteFlag().equals("N")) {
            BillingAddressEntity ba = new BillingAddressEntity();
            ShippingAddressEntity sa = new ShippingAddressEntity();
            if (billingId != 0) {
                ba = em.find(BillingAddressEntity.class, billingId);
                if (ba != null) {
                    soe.setBillingAddress(ba);
                }
            }
            if (shippingId != 0) {
                sa = em.find(ShippingAddressEntity.class, shippingId);
                if (sa != null) {
                    soe.setShippingAddress(sa);
                }
            }

            soe.setDateIssued(dateIssued);
            soe.setStatus(status);
            soe.setATPCheckStatus(ATPCheckStatus);
            soe.setCreditCheckStatus(creditCheckStatus);

            soe.setDescription(description);
            soe.setDocumentName(docName);
            soe.setDueDate(dueDate);
            soe.setCurrency(currency);
            soe.setShippingMethod(shippingMethod);
            soe.setShippingRule(shippingRule);
            soe.setInvoiceRule(invoiceRule);
            soe.setPaymentMethod(paymentMethod);

            if (paymentMethod.equals("Cash")) {
                if (soe.isCashInAdvanced()) {
                    //do nothing
                } else {
                    soe.setCashInAdvanced(true);
                    System.out.println("Notify finance dept for CIA");
                    informCashInAdvancePayment(id, clientId);
                }
            } else {
                soe.setCashInAdvanced(false);
            }

            soe.setPriority(priority);
            soe.setFreightCostRule(freightCostRule);


            System.out.println("Edit status of sales order");
            if (status.equals("Approved")) {
                if (!soe.isIsApproved()) {
                    System.out.println("Not approved before, so create delivery order!");
                    confirmReservationsOnSalesOrder(soe.getBackOrder().getId());
                    createDeliveryandPickingOrder(soe.getId());
                    System.out.println("Delivery and picking order created");
                    soe.setIsApproved(true);
                }
                soe.setIsCompleted(false);               
                soe.setIsRejected(false);    
                soe.setIsVoided(false);
            } else if (status.equals("Completed")) {
                System.out.println("Status is completed");
                soe.setIsCompleted(true);             
                soe.setIsRejected(false);         
                soe.setIsVoided(false);
                soe.setIsApproved(false);
            } else if (status.equals("Rejected")) {
                soe.setIsRejected(true);
                soe.setIsCompleted(false);
                soe.setIsVoided(false);
                soe.setIsApproved(false);
            } else if (status.equals("Voided")) {
                if (!soe.isIsVoided()) {
                    System.out.println("If status equals voided");
                    soe.setIsVoided(true);
                    if (soe.isCashInAdvanced()) {
                        System.out.println("If mode of payment is CIA");
                        this.requestRefund(soe.getClient().getId(), soe.getId());
                    }
                    System.out.println("Withdraw delivery order");
                    for (Object o : soe.getDeliveryOrderList()) {
                        DeliveryOrderEntity doe = (DeliveryOrderEntity) o;
                        imm.withdrawDeliveryOrder(doe.getId());
                    }
                
                    System.out.println("Withdraw reservation");
                    if (soe.getBackOrder() != null) {
                        Long backOrderId = soe.getBackOrder().getId();
                        annulReservationsOnSalesOrder(backOrderId);
                    }
                }
                soe.setIsCompleted(false);
                soe.setIsRejected(false);
                soe.setIsApproved(false);
            } else if (creditCheckStatus.equals("Rejected")) {
                soe.setStatus("Rejected");
                soe.setIsRejected(true);
                soe.setIsCompleted(false);
                soe.setIsVoided(false);
                soe.setIsApproved(false);
            }

            if (contactId != null) {
                ContactEntity contact = em.find(ContactEntity.class, contactId);
                soe.setContact(contact);
            }

            ClientEntity client = em.find(ClientEntity.class, clientId);
            if (client != null && client.getDeleteFlag().equals("N")) {
                soe.setClient(client);
                em.flush();
                result = "Client found.";
            } else {
                System.out.println("Client not found");
                result = "Client not found.";
            }

            PurchaseOrderEntity po = em.find(PurchaseOrderEntity.class, poId);
            if (po != null && po.getDeleteFlag().equals("N")) {
                soe.setPurchaseOrder(po);
                em.flush();

            } else {
                System.out.println("PO not found");

            }
            result = result + "SO found";
        } else {
            System.out.println("Sales order not found");
            result = "SO not found";
        }

    }

    public String deleteSalesOrder(Long id) {

         System.out.println("deleteSalesOrder");
        String result;
       
        SalesOrderEntity soe = em.find(SalesOrderEntity.class, id);
        if (soe != null) {

            if (!soe.getStatus().equals("Voided")) {
                if (soe.isCashInAdvanced()) {
                    this.requestRefund(soe.getClient().getId(), soe.getId());
                }
                System.out.println("Status not voided before, so annul reservations and delivery order!");
                System.out.println("Withdraw delivery order");
                 for(Object o : soe.getDeliveryOrderList()){
                    DeliveryOrderEntity doe = (DeliveryOrderEntity) o;
                    imm.withdrawDeliveryOrder(doe.getId());    
                }
                
                System.out.println("Withdraw reservation");
                if (soe.getBackOrder() != null) {
                    Long backOrderId = soe.getBackOrder().getId();
                    annulReservationsOnSalesOrder(backOrderId);
                }
            }

            soe.setDeleteFlag("Y");
            em.flush();

            System.out.println("Find line entry list");
            Collection<LineEntryEntity> lineEntryList = soe.getLineEntryList();
            for (Object l : lineEntryList) {
                System.out.println("Line entry found");
                LineEntryEntity lineEntry = (LineEntryEntity) l;
                lineEntry.setDeleteFlag("Y");
                em.flush();
            }
            result = "SO deleted";
        } else {
            result = "SO not found";
        }

        return result;
    }

    public List<ProductState> viewProductList() {

        System.out.println("view Product List");
        Query q = em.createQuery("SELECT a from ProductEntity a");
        List stateList = new ArrayList();

        for (Object o : q.getResultList()) {
            ProductEntity p = (ProductEntity) o;
            ProductState pState = new ProductState(p.getId(), p.getName(), p.getDescription(),
                    p.getBasePrice(), p.getListPrice(), p.getLimitPrice(), p.getPricebook());

            stateList.add(pState);
        }

        return stateList;

    }

    public List<SalesDocumentState> viewSalesInquiries() {
        
        System.out.println("view Sales Inquiries");

        Query q = em.createQuery("SELECT c FROM SalesInquiryEntity c");
        List stateList = new ArrayList();

        for (Object o : q.getResultList()) {
            SalesInquiryEntity c = (SalesInquiryEntity) o;
            if (c.getDocumentType().equals("SI") && c.getDeleteFlag().equals("N")
                    && !c.getStatus().equals("Converted") && smb.checkClientStatus(c.getClient())) {
                double totalPrice = 0;
                double price;
                String type = c.getPricingType();

                Collection<LineEntryEntity> lineEntryList = c.getLineEntryList();
                for (Object l : lineEntryList) {
                    LineEntryEntity lineEntry = (LineEntryEntity) l;                   
                    totalPrice = totalPrice + lineEntry.getTotalLinePrice();
                }

                SalesDocumentState sdState = new SalesDocumentState(c.getId(), c.getDateIssued(),
                        c.getClient().getId(), c.getClient().getName(),
                        c.getStatus(), c.getLineEntryList());
                sdState.setTotalPrice(totalPrice);
                sdState.setClient(c.getClient());
                if (c.getContact() != null) {
                    sdState.setContactId(c.getContact().getId());
                    sdState.setContactName(c.getContact().getFirstName() + c.getContact().getLastName());
                } else {
                    sdState.setContactId(Long.parseLong("0"));
                    sdState.setContactName("Not yet specified");
                }
                sdState.setDescription(c.getDescription());
                sdState.setDocumentName(c.getDocumentName());
                sdState.setPricingType(type);
                if (c.getStatus().equals("Voided")) {
                    sdState.setVoided(true);
                }
                stateList.add(sdState);
            }
        }
        return stateList;
    }

    public List<SalesDocumentState> viewConvertedInquiries() {
        
        System.out.println("view Converted Sales Inquiries");

        Query q = em.createQuery("SELECT c FROM SalesInquiryEntity c");
        List stateList = new ArrayList();

        for (Object o : q.getResultList()) {
            SalesInquiryEntity c = (SalesInquiryEntity) o;
            if (c.getDocumentType().equals("SI") && c.getDeleteFlag().equals("N")
                    && c.getStatus().equals("Converted") && smb.checkClientStatus(c.getClient())) {
                double totalPrice = 0;
                double price;
                String type = c.getPricingType();

                Collection<LineEntryEntity> lineEntryList = c.getLineEntryList();
                for (Object l : lineEntryList) {
                    LineEntryEntity lineEntry = (LineEntryEntity) l;
                    totalPrice = totalPrice + lineEntry.getTotalLinePrice();
                }

                SalesDocumentState sdState = new SalesDocumentState(c.getId(), c.getDateIssued(),
                        c.getClient().getId(), c.getClient().getName(),
                        c.getStatus(), c.getLineEntryList());
                sdState.setTotalPrice(totalPrice);
                sdState.setClient(c.getClient());
                if (c.getContact() != null) {
                    sdState.setContactId(c.getContact().getId());
                    sdState.setContactName(c.getContact().getFirstName() + c.getContact().getLastName());
                } else {
                    sdState.setContactId(Long.parseLong("0"));
                    sdState.setContactName("Not yet specified");
                }
                sdState.setDescription(c.getDescription());
                sdState.setDocumentName(c.getDocumentName());
                sdState.setPricingType(type);
                stateList.add(sdState);
            }
        }
        return stateList;
    }

    public List<SalesDocumentState> viewQuotations() {
        System.out.println("view Quotations");

        Query q = em.createQuery("SELECT c FROM QuotationEntity c");
        List stateList = new ArrayList();

        if (q.getResultList() != null) {
            System.out.println("Result list not null");
        }
        for (Object o : q.getResultList()) {
            QuotationEntity c = (QuotationEntity) o;
            if (c.getDocumentType().equals("QN") && c.getDeleteFlag().equals("N") && !c.getStatus().equals("Converted")
                    && c.getClient().getDeleteFlag().equals("N") && smb.checkClientStatus(c.getClient())/* && c.getReservationEntity()!=null*/) {
                double price;
                double totalPrice = 0;
                String type = c.getPricingType();
                Collection<LineEntryEntity> lineEntryList = c.getLineEntryList();
                for (Object l : lineEntryList) {
                    LineEntryEntity lineEntry = (LineEntryEntity) l;
                    totalPrice = totalPrice + lineEntry.getTotalLinePrice();
                }

                SalesDocumentState sdState = new SalesDocumentState(c.getId(), c.getDateIssued(),
                        c.getvalidUntil(), c.getIndicativeLeadtime(),
                        c.getClient().getId(), c.getClient().getName(),
                        c.getLineEntryList());
                if (c.getContact() != null) {
                    sdState.setContactId(c.getContact().getId());
                    sdState.setContactName(c.getContact().getFirstName() + c.getContact().getLastName());
                } else {
                    sdState.setContactId(Long.parseLong("0"));
                    sdState.setContactName("Not yet specified");
                }
                sdState.setTotalPrice(round(totalPrice));
                sdState.setDescription(c.getDescription());
                sdState.setDocumentName(c.getDocumentName());
                sdState.setPricingType(type);
                sdState.setReferred(c.isReferred());
                sdState.setStatus(c.getStatus());
                if (c.getStatus().equals("Voided")) {
                    sdState.setVoided(true);
                }

                stateList.add(sdState);
            }
        }
        return stateList;
    }

    public List<SalesDocumentState> viewConvertedQuotations() {

        System.out.println("viewConvertedQuotations");

        Query q = em.createQuery("SELECT c FROM QuotationEntity c");
        List stateList = new ArrayList();

        if (q.getResultList() != null) {
            System.out.println("Result list not null");
        }
        for (Object o : q.getResultList()) {
            QuotationEntity c = (QuotationEntity) o;
            if (c.getDocumentType().equals("QN") && c.getDeleteFlag().equals("N") && c.getStatus().equals("Converted")
                    && c.getClient().getDeleteFlag().equals("N") && smb.checkClientStatus(c.getClient())/* && c.getReservationEntity()!=null*/) {
                double price;
                double totalPrice = 0;
                String type = c.getPricingType();
                Collection<LineEntryEntity> lineEntryList = c.getLineEntryList();
                for (Object l : lineEntryList) {
                    LineEntryEntity lineEntry = (LineEntryEntity) l;
                    totalPrice = totalPrice + lineEntry.getTotalLinePrice();
                }

                SalesDocumentState sdState = new SalesDocumentState(c.getId(), c.getDateIssued(),
                        c.getvalidUntil(), c.getIndicativeLeadtime(),
                        c.getClient().getId(), c.getClient().getName(),
                        c.getLineEntryList());
                if (c.getContact() != null) {
                    sdState.setContactId(c.getContact().getId());
                    sdState.setContactName(c.getContact().getFirstName() + c.getContact().getLastName());
                } else {
                    sdState.setContactId(Long.parseLong("0"));
                    sdState.setContactName("Not yet specified");
                }
                sdState.setTotalPrice(round(totalPrice));
                sdState.setDescription(c.getDescription());
                sdState.setDocumentName(c.getDocumentName());
                sdState.setPricingType(type);
                sdState.setReferred(c.isReferred());

                stateList.add(sdState);
            }
        }
        return stateList;
    }

    public List<SalesDocumentState> viewPurchaseOrders() {
        System.out.println("viewPurchaseOrders");

        Query q = em.createQuery("SELECT c FROM PurchaseOrderEntity c");
        List<SalesDocumentState> stateList = new ArrayList();

        for (Object o : q.getResultList()) {
            PurchaseOrderEntity c = (PurchaseOrderEntity) o;
            if (c.getDocumentType().equals("PO") && c.getDeleteFlag().equals("N") && !c.getStatus().equals("Converted")
                    && c.getClient().getDeleteFlag().equals("N") && smb.checkClientStatus(c.getClient()) /*&& c.getReservationEntity()!=null*/) {

                double totalPrice = 0;
                double price;
                String type = c.getPricingType();

                Collection<LineEntryEntity> lineEntryList = c.getLineEntryList();
                for (Object l : lineEntryList) {
                    LineEntryEntity lineEntry = (LineEntryEntity) l;
                    totalPrice = totalPrice + lineEntry.getTotalLinePrice();
                }

                Long id = c.getQuotation().getId();
                SalesDocumentState sdState = new SalesDocumentState(c.getId(), c.getDateIssued(),
                        c.getClient().getId(), c.getClient().getName(),
                        c.getStatus(), c.getLineEntryList(), c.getQuotation(), id);
                sdState.setLeadTime(c.getQuotation().getIndicativeLeadtime());
                sdState.setTotalPrice(totalPrice);
                sdState.setDescription(c.getDescription());
                sdState.setDocumentName(c.getDocumentName());
                sdState.setDueDate(c.getDueDate());
                sdState.setShippingMethod(c.getShippingMethod());
                sdState.setShippingRule(c.getShippingRule());
                sdState.setInvoiceRule(c.getInvoiceRule());
                sdState.setPaymentMethod(c.getPaymentMethod());
                sdState.setFreightCostRule(c.getFreightCostRule());
                sdState.setCurrency(c.getCurrency());
                sdState.setPricingType(type);
                if (c.getStatus().equals("Voided")) {
                    sdState.setVoided(true);
                }

                sdState.setReferred(c.isReferred());
                sdState.setLeadTime(c.getLeadTime());
                if (c.getContact() != null) {
                    sdState.setContactId(c.getContact().getId());
                    sdState.setContactName(c.getContact().getFirstName() + c.getContact().getLastName());
                } else {
                    sdState.setContactId(Long.parseLong("0"));
                    sdState.setContactName("Not yet specified");
                }


                BillingAddressEntity ba = c.getBillingAddress();
                if (ba != null) {
                    System.out.println("Billing address not null");
                }
                System.out.println("Billing id" + ba.getId());
                sdState.setBillingId(ba.getId());
                sdState.setBillingStreet(ba.getBillingStreet());
                sdState.setBillingState(ba.getBillingState());
                sdState.setBillingCity(ba.getBillingCity());
                sdState.setBillingCode(ba.getBillingCode());
                sdState.setBillingCountry(ba.getBillingCountry());

                ShippingAddressEntity sa = c.getShippingAddress();
                sdState.setShippingId(sa.getId());
                sdState.setShippingStreet(sa.getShippingStreet());
                sdState.setShippingState(sa.getShippingState());
                sdState.setShippingCity(sa.getShippingCity());
                sdState.setShippingCode(sa.getShippingCode());
                sdState.setShippingCountry(sa.getShippingCountry());

                stateList.add(sdState);
            }
        }
        return stateList;
    }

    public List<SalesDocumentState> viewConvertedPurchaseOrders() {
        System.out.println("viewConvertedPurchaseOrders");

        Query q = em.createQuery("SELECT c FROM PurchaseOrderEntity c");
        List<SalesDocumentState> stateList = new ArrayList();

        for (Object o : q.getResultList()) {
            PurchaseOrderEntity c = (PurchaseOrderEntity) o;
            if (c.getDocumentType().equals("PO") && c.getDeleteFlag().equals("N") && c.getStatus().equals("Converted")
                    && c.getClient().getDeleteFlag().equals("N") && smb.checkClientStatus(c.getClient()) /*&& c.getReservationEntity()!=null*/) {
                double totalPrice = 0;
                double price;
                String type = c.getPricingType();

                Collection<LineEntryEntity> lineEntryList = c.getLineEntryList();
                for (Object l : lineEntryList) {
                    LineEntryEntity lineEntry = (LineEntryEntity) l;
                    totalPrice = totalPrice + lineEntry.getTotalLinePrice();
                }

                Long id = c.getQuotation().getId();
                SalesDocumentState sdState = new SalesDocumentState(c.getId(), c.getDateIssued(),
                        c.getClient().getId(), c.getClient().getName(),
                        c.getStatus(), c.getLineEntryList(), c.getQuotation(), id);
                sdState.setLeadTime(c.getQuotation().getIndicativeLeadtime());
                sdState.setTotalPrice(totalPrice);
                sdState.setDescription(c.getDescription());
                sdState.setDocumentName(c.getDocumentName());
                sdState.setDueDate(c.getDueDate());
                sdState.setShippingMethod(c.getShippingMethod());
                sdState.setShippingRule(c.getShippingRule());
                sdState.setInvoiceRule(c.getInvoiceRule());
                sdState.setPaymentMethod(c.getPaymentMethod());
                sdState.setFreightCostRule(c.getFreightCostRule());
                sdState.setCurrency(c.getCurrency());
                sdState.setPricingType(type);
                sdState.setReferred(c.isReferred());
                if (c.getContact() != null) {
                    sdState.setContactId(c.getContact().getId());
                    sdState.setContactName(c.getContact().getFirstName() + c.getContact().getLastName());
                } else {
                    sdState.setContactId(Long.parseLong("0"));
                    sdState.setContactName("Not yet specified");
                }
                BillingAddressEntity ba = c.getBillingAddress();
                sdState.setBillingId(ba.getId());
                sdState.setBillingStreet(ba.getBillingStreet());
                sdState.setBillingState(ba.getBillingState());
                sdState.setBillingCity(ba.getBillingCity());
                sdState.setBillingCode(ba.getBillingCode());
                sdState.setBillingCountry(ba.getBillingCountry());

                ShippingAddressEntity sa = c.getShippingAddress();
                sdState.setShippingId(sa.getId());
                sdState.setShippingStreet(sa.getShippingStreet());
                sdState.setShippingState(sa.getShippingState());
                sdState.setShippingCity(sa.getShippingCity());
                sdState.setShippingCode(sa.getShippingCode());
                sdState.setShippingCountry(sa.getShippingCountry());

                stateList.add(sdState);
            }
        }
        return stateList;
    }

    public List<SalesDocumentState> viewSalesOrders() {
        System.out.println("viewSalesOrders");


        Query q = em.createQuery("SELECT c FROM SalesOrderEntity c");
        List stateList = new ArrayList();

        for (Object o : q.getResultList()) {
            SalesOrderEntity c = (SalesOrderEntity) o;
            if (c.getDocumentType().equals("SO") && c.getDeleteFlag().equals("N")
                    && c.getClient().getDeleteFlag().equals("N") && smb.checkClientStatus(c.getClient())) {
                double totalPrice = 0;
                double price;
                String type = c.getPricingType();

                Collection<LineEntryEntity> lineEntryList = c.getLineEntryList();
                for (Object l : lineEntryList) {
                    LineEntryEntity lineEntry = (LineEntryEntity) l;
                    totalPrice = totalPrice + lineEntry.getTotalLinePrice();
                }

                SalesDocumentState sdState = new SalesDocumentState(c.getId(), c.getDateIssued(),
                        c.getClient().getId(), c.getClient().getName(),
                        c.getStatus(), c.getATPCheckStatus(), c.getCreditCheckStatus(),
                        c.getLineEntryList(), c.getPurchaseOrder(), c.getPurchaseOrder().getId());
   
                sdState.setTotalPrice(totalPrice);
                sdState.setDescription(c.getDescription());
                sdState.setLeadTime(c.getPurchaseOrder().getQuotation().getIndicativeLeadtime());
                sdState.setConfirmedLeadTime(c.getleadTimeConfirmed());
                sdState.setDocumentName(c.getDocumentName());
                sdState.setDueDate(c.getDueDate());
                sdState.setShippingMethod(c.getShippingMethod());
                sdState.setShippingRule(c.getShippingRule());
                sdState.setInvoiceRule(c.getInvoiceRule());
                sdState.setPaymentMethod(c.getPaymentMethod());
                sdState.setFreightCostRule(c.getFreightCostRule());
                sdState.setCurrency(c.getCurrency());
                sdState.setApproved(c.isIsApproved());
                sdState.setVoided(c.isIsVoided());
                sdState.setCompleted(c.isIsCompleted());
                sdState.setRejected(c.isIsRejected());
                sdState.setCashInAdvanced(c.isCashInAdvanced());
                sdState.setPricingType(type);
                sdState.setReferred(c.isReferred());
                if (c.getContact() != null) {
                    sdState.setContactId(c.getContact().getId());
                    sdState.setContactName(c.getContact().getFirstName() + c.getContact().getLastName());
                } else {
                    sdState.setContactId(Long.parseLong("0"));
                    sdState.setContactName("Not yet specified");
                }
                BillingAddressEntity ba = c.getBillingAddress();
                sdState.setBillingId(ba.getId());
                sdState.setBillingStreet(ba.getBillingStreet());
                sdState.setBillingState(ba.getBillingState());
                System.out.println("View PO : " + sdState.getBillingState());
                sdState.setBillingCity(ba.getBillingCity());
                sdState.setBillingCode(ba.getBillingCode());
                sdState.setBillingCountry(ba.getBillingCountry());

                ShippingAddressEntity sa = c.getShippingAddress();
                sdState.setShippingId(sa.getId());
                sdState.setShippingStreet(sa.getShippingStreet());
                sdState.setShippingState(sa.getShippingState());
                sdState.setShippingCity(sa.getShippingCity());
                sdState.setShippingCode(sa.getShippingCode());
                sdState.setShippingCountry(sa.getShippingCountry());


                stateList.add(sdState);

            }
        }
        return stateList;
    }

    public List<SalesDocumentState> viewApprovedSalesOrders() {
        System.out.println("viewSalesOrders");


        Query q = em.createQuery("SELECT c FROM SalesOrderEntity c");
        List stateList = new ArrayList();

        for (Object o : q.getResultList()) {
            SalesOrderEntity c = (SalesOrderEntity) o;
            if (c.getDocumentType().equals("SO") && c.getDeleteFlag().equals("N")
                    && c.getClient().getDeleteFlag().equals("N") && c.getStatus().equals("Approved")) {
                double totalPrice = 0;
                double price;
                String type = c.getPricingType();

                Collection<LineEntryEntity> lineEntryList = c.getLineEntryList();
                for (Object l : lineEntryList) {
                    LineEntryEntity lineEntry = (LineEntryEntity) l;

                    totalPrice = totalPrice + lineEntry.getTotalLinePrice();
                }

                SalesDocumentState sdState = new SalesDocumentState(c.getId(), c.getDateIssued(),
                        c.getClient().getId(), c.getClient().getName(),
                        c.getStatus(), c.getATPCheckStatus(), c.getCreditCheckStatus(),
                        c.getLineEntryList(), c.getPurchaseOrder(), c.getPurchaseOrder().getId());
                
                sdState.setTotalPrice(totalPrice); 
                sdState.setDescription(c.getDescription());
                sdState.setLeadTime(c.getPurchaseOrder().getQuotation().getIndicativeLeadtime());
                sdState.setConfirmedLeadTime(c.getleadTimeConfirmed());
                sdState.setDocumentName(c.getDocumentName());
                sdState.setDueDate(c.getDueDate());
                sdState.setShippingMethod(c.getShippingMethod());
                sdState.setShippingRule(c.getShippingRule());
                sdState.setInvoiceRule(c.getInvoiceRule());
                sdState.setPaymentMethod(c.getPaymentMethod());
                sdState.setFreightCostRule(c.getFreightCostRule());
                sdState.setCurrency(c.getCurrency());
                sdState.setApproved(c.isIsApproved());
                sdState.setVoided(c.isIsVoided());
                sdState.setCompleted(c.isIsCompleted());
                sdState.setRejected(c.isIsRejected());
                sdState.setCashInAdvanced(c.isCashInAdvanced());
                sdState.setPricingType(type);
                sdState.setReferred(c.isReferred());
                
                if (c.getContact() != null) {
                    sdState.setContactId(c.getContact().getId());
                    sdState.setContactName(c.getContact().getFirstName() + c.getContact().getLastName());
                } else {
                    sdState.setContactId(Long.parseLong("0"));
                    sdState.setContactName("Not yet specified");
                }
                BillingAddressEntity ba = c.getBillingAddress();
                sdState.setBillingId(ba.getId());
                sdState.setBillingStreet(ba.getBillingStreet());
                sdState.setBillingState(ba.getBillingState());
                System.out.println("View PO : " + sdState.getBillingState());
                sdState.setBillingCity(ba.getBillingCity());
                sdState.setBillingCode(ba.getBillingCode());
                sdState.setBillingCountry(ba.getBillingCountry());

                ShippingAddressEntity sa = c.getShippingAddress();
                sdState.setShippingId(sa.getId());
                sdState.setShippingStreet(sa.getShippingStreet());
                sdState.setShippingState(sa.getShippingState());
                sdState.setShippingCity(sa.getShippingCity());
                sdState.setShippingCode(sa.getShippingCode());
                sdState.setShippingCountry(sa.getShippingCountry());


                stateList.add(sdState);

            }
        }
        return stateList;
    }

    public List<LineEntryState> viewProductListforSalesDocument(Long id) {

        System.out.println("view Product List for Sales Document");

        SalesDocumentEntity sd = em.find(SalesDocumentEntity.class, id);
        if (sd != null) {
            System.out.println("Sales document found");
        }

        Collection<LineEntryEntity> lineEntryList = sd.getLineEntryList();

        List<LineEntryState> lesList = new ArrayList();
        if (lineEntryList != null) {
            System.out.println("Line entry list is not null");
            for (Object o : lineEntryList) {
                LineEntryEntity lineEntry = (LineEntryEntity) o;
                Long itemId = lineEntry.getItemId();
                System.out.println(itemId);
                String itemName = lineEntry.getItemName();
                int quantity = lineEntry.getQuantity();
                double price = lineEntry.getPrice();
                double basePrice = lineEntry.getBasePrice();
                Long pricebookId = lineEntry.getPricebookId();

                LineEntryState les = new LineEntryState(itemId, itemName, quantity, price);
                les.setId(lineEntry.getId());
                les.setIndicativeLeadTime(lineEntry.getLeadTime());
                les.setBasePrice(lineEntry.getBasePrice());
                les.setAmountInvoiced(lineEntry.getAmountInvoiced());
                les.setAmountShipped(lineEntry.getAmountShipped());
                les.setTotalPrice(lineEntry.getTotalLinePrice());
                les.setPricebookId(pricebookId);
                les.setAmountInDeliveryOrder(lineEntry.getAmountInDeliveryOrder());
                les.setPricingType(sd.getPricingType());
                lesList.add(les);

            }
        }

        return lesList;
    }

    public List<LineEntryState> viewProductListforDeliveryOrder(Long id) {

        System.out.println("view Product List for Delivery Order");

        DeliveryOrderEntity sd = em.find(DeliveryOrderEntity.class, id);
        if (sd != null) {
            System.out.println("Delivery order found");
        }

        List<LineEntryEntity> lineEntryList = sd.getLineEntryList();

        List<LineEntryState> lesList = new ArrayList<LineEntryState>();
        if (lineEntryList != null) {
            System.out.println("Line entry list is not null");
            for (Object o : lineEntryList) {
                LineEntryEntity lineEntry = (LineEntryEntity) o;
                Long itemId = lineEntry.getItemId();
                System.out.println(itemId);
                String itemName = lineEntry.getItemName();
                int quantity = lineEntry.getQuantity();
                double price = lineEntry.getPrice();
                double basePrice = lineEntry.getBasePrice();
                Long pricebookId = lineEntry.getPricebookId();

                LineEntryState les = new LineEntryState(itemId, itemName, quantity, price);
                les.setId(lineEntry.getId());

                les.setIndicativeLeadTime(lineEntry.getLeadTime());
                System.out.println("Lead Time : " + lineEntry.getLeadTime());
                les.setBasePrice(lineEntry.getBasePrice());
                les.setAmountInvoiced(lineEntry.getAmountInvoiced());
                les.setAmountShipped(lineEntry.getAmountShipped());
                les.setAmountInDeliveryOrder(lineEntry.getAmountInDeliveryOrder());
                les.setTotalPrice(round(lineEntry.getTotalLinePrice()));
                les.setPricebookId(pricebookId);
                les.setPricingType(sd.getPricingType());
                lesList.add(les);

            }
        }

        return lesList;
    }

    public double getTotalPrice(LineEntryEntity lineEntry, String type) {

        double total = 0;

        int quantity = lineEntry.getQuantity();
        Long productId = lineEntry.getItemId();

        PricebookEntity pricebook = em.find(PricebookEntity.class, lineEntry.getPricebookId());


        double listPrice = 0;
        double[][] priceArr = pricebook.getPriceArr();

        if (type.equals("F")) {

            listPrice = lineEntry.getPrice();
            total = quantity * listPrice;

        } else if (type.equals("D")) {
            for (int i = 0; i < priceArr.length; i++) {
                if (quantity < priceArr[i][1]) {
                    System.out.println("Less than");
                    listPrice = lineEntry.getPrice();
                    quantity = quantity - (int) priceArr[i][0] + 1;
                    total = total + quantity * listPrice;
                    System.out.println("i=" + i + " Total = " + total);
                    break;
                } else {
                    System.out.println("More than");
                    listPrice = priceArr[i][2];
                    total = total + (priceArr[i][1] - priceArr[i][0] + 1) * listPrice;
                    System.out.println("i : " + i + " Total : " + total + "Qty: " + quantity);
                    continue;

                }
            }
        }

        return round(total);

    }

    public double getTotalPrice(LineEntryState lineEntry, String type) {

        double total = 0;

        int quantity = lineEntry.getQuantity();
        Long productId = lineEntry.getItemId();

        PricebookEntity pricebook = em.find(PricebookEntity.class, lineEntry.getPricebookId());


        double listPrice = 0;
        double[][] priceArr = pricebook.getPriceArr();

        if (type.equals("F")) {

            listPrice = lineEntry.getPrice();
            total = quantity * listPrice;

        } else if (type.equals("D")) {
            for (int i = 0; i < priceArr.length; i++) {
                if (quantity < priceArr[i][1]) {
                    System.out.println("Less than");
                    listPrice = lineEntry.getPrice();
                    quantity = quantity - (int) priceArr[i][0] + 1;
                    total = total + quantity * listPrice;
                    System.out.println("i=" + i + " Total = " + total);
                    break;
                } else {
                    System.out.println("More than");
                    listPrice = priceArr[i][2];
                    total = total + (priceArr[i][1] - priceArr[i][0] + 1) * listPrice;
                    System.out.println("i : " + i + " Total : " + total + "Qty: " + quantity);
                    continue;

                }
            }
        }

        return round(total);

    }

    public double getBasePrice(Long id) {

        ProductEntity product = em.find(ProductEntity.class, id);
        double basePrice = product.getBasePrice();

        return basePrice;
    }

    public void createPriceBook(String name, Long productId, double[][] arr) {
        ProductEntity product = em.find(ProductEntity.class, productId);
        double listPrice = 0;
        if (product != null) {
            listPrice = product.getListPrice();
        }

        int n = arr.length;

        double[][] priceList = new double[n][4];

        for (int i = 0; i < n; i++) {
            priceList[i][0] = arr[i][0];
            priceList[i][1] = arr[i][1];
            priceList[i][2] = ((100.0 - arr[i][2]) / 100) * listPrice;//direct 
            priceList[i][3] = ((100.0 - arr[i][3]) / 100) * listPrice;//wholesale
        }

        PricebookEntity pricebook = new PricebookEntity();

        pricebook.create(priceList, productId);
        em.persist(pricebook);
        pricebook.setName(name);
        pricebook.setDeleteFlag("N");
        em.flush();
        List<PricebookEntity> pricebookList = product.getPricebook();
        pricebookList.add(pricebook);
        iib.setPriceBook(pricebookList, productId);
        em.flush();

    }

    public void createPricebook2(String name, Long productId, List<PricebookEntryState> entryList) {

        ProductEntity product = em.find(ProductEntity.class, productId);
        double listPrice = 0;
        if (product != null) {
            listPrice = product.getListPrice();
        }


        int n = entryList.size();
        System.out.println("size  : " + n);

        double[][] priceList = new double[n][4];

        for (int i = 0; i < n; i++) {
            priceList[i][0] = entryList.get(i).getLow();
            priceList[i][1] = entryList.get(i).getHigh();
            priceList[i][2] = ((100.0 - (entryList.get(i).getDirectDisc())) / 100) * listPrice;//direct 
            System.out.println("Direct Price " + priceList[i][2]);
            priceList[i][3] = ((100.0 - (entryList.get(i).getWholesaleDisc())) / 100) * listPrice;//wholesale
            System.out.println("Wholesale Price " + priceList[i][3]);
        }

        PricebookEntity pricebook = new PricebookEntity();

        pricebook.create(priceList, productId);
        em.persist(pricebook);
        pricebook.setName(name);
        pricebook.setDeleteFlag("N");
        em.flush();
        List<PricebookEntity> pricebookList = product.getPricebook();
        pricebookList.add(pricebook);
        iib.setPriceBook(pricebookList, productId);
        em.flush();
    }

    public double getListPrice(int quantity, String type, Long pricebookId) {

        PricebookEntity pricebook = em.find(PricebookEntity.class, pricebookId);

        double listPrice = 0;
        double[][] priceArr = pricebook.getPriceArr();
        boolean isFound = false;

        if (type.equals("Direct")) {
            for (int i = 0; i < priceArr.length; i++) {
                if (quantity > (int) priceArr[i][1]) {
                    continue;
                } else {
                    listPrice = priceArr[i][2];
                    isFound = true;
                    break;
                }
            }
            if (!isFound) {
                listPrice = priceArr[priceArr.length - 1][2];
            }
        } else {

            for (int i = 0; i < priceArr.length; i++) {
                if (quantity > (int) priceArr[i][1]) {
                    continue;
                } else {
                    listPrice = priceArr[i][3];
                    isFound = true;
                    break;
                }
            }
            if (!isFound) {
                listPrice = priceArr[priceArr.length - 1][3];
            }
        }

        listPrice = round(listPrice);
        return listPrice;

    }

    public List<PricebookEntity> getPricebook(Long id) {

        ProductEntity product = em.find(ProductEntity.class, id);
        List<PricebookEntity> pricebookList = product.getPricebook();
        List<PricebookEntity> list = new ArrayList<PricebookEntity>();
        for (Object o : pricebookList) {
            PricebookEntity p = (PricebookEntity) o;
            if (!p.getDeleteFlag().equals("Y")) {
                list.add(p);
            }
        }

        System.out.println(list.size());
        return list;
    }

    public List<PricebookEntity> getPricebookList() {

        Query q = em.createQuery("SELECT a from PricebookEntity a where a.deleteFlag='N' ");
        List<PricebookEntity> pricebookList = q.getResultList();
        System.out.println("Price book 1 " + pricebookList.get(0).getId());

        return pricebookList;
    }

    public List<PricebookState> getPricebookState(Long id) {

        ProductEntity product = em.find(ProductEntity.class, id);
        List<PricebookState> pricebookList = new ArrayList<PricebookState>();
       
        List<PricebookEntryState> entryList = new ArrayList<PricebookEntryState>();
        List<PricebookEntity> priceList = product.getPricebook();

        for (Object o : priceList) {
            PricebookEntity p = (PricebookEntity) o;
            if (!p.getDeleteFlag().equals("Y")) {
                double[][] priceArr = p.getPriceArr();
                for (int i = 0; i < priceArr.length; i++) {
                    int low = (int) priceArr[i][0];
                    int high = (int) priceArr[i][1];
                    double directPrice = round(priceArr[i][2]);
                    double wholesalePrice = round(priceArr[i][3]);
                    // int number = i+1;
                    PricebookEntryState pricebookEntry = new PricebookEntryState(low, high, directPrice, wholesalePrice);
                    pricebookEntry.setPricebookId(p.getId());
                    pricebookEntry.setNumber(i);
                    entryList.add(pricebookEntry);

                }
                PricebookState prState = new PricebookState(p.getId(), p.getProductId(), p.IsActive(), entryList);
                prState.setName(p.getName());
                pricebookList.add(prState);
            }
        }

        for (Object p : entryList) {
            PricebookEntryState a = (PricebookEntryState) p;
            System.out.println(a.getLow());
            System.out.println(a.getHigh());
            System.out.println(a.getDirectPrice());
            System.out.println(a.getWholesalePrice());
        }

        return pricebookList;
    }

    public double round(double d) {
        DecimalFormat twoDForm = new DecimalFormat("#.##");
        return Double.valueOf(twoDForm.format(d));
    }

    public List<PricebookState> getPricebookStateList() {

        List<PricebookState> pricebookList = new ArrayList<PricebookState>();
        Query q = em.createQuery("Select a from PricebookEntity a where a.deleteFlag='N'");
        List<PricebookEntryState> entryList = new ArrayList<PricebookEntryState>();

        for (Object o : q.getResultList()) {
            PricebookEntity p = (PricebookEntity) o;
            double[][] priceArr = p.getPriceArr();
            for (int i = 0; i < priceArr.length; i++) {
                int low = (int) priceArr[i][0];
                int high = (int) priceArr[i][1];
                double directPrice = round(priceArr[i][2]);
                double wholesalePrice = round(priceArr[i][3]);
                // int number = i+1;
                PricebookEntryState pricebookEntry = new PricebookEntryState(low, high, directPrice, wholesalePrice);
                pricebookEntry.setPricebookId(p.getId());
                pricebookEntry.setNumber(i);
                entryList.add(pricebookEntry);
            }
            PricebookState prState = new PricebookState(p.getId(), p.getProductId(), p.IsActive(), entryList);
            prState.setName(p.getName());
            pricebookList.add(prState);
        }

        return pricebookList;

    }

    public List<PricebookEntryState> getPricebookEntry(Long id) {

        List<PricebookEntryState> entryList = new ArrayList<PricebookEntryState>();
        PricebookEntity p = em.find(PricebookEntity.class, id);
        double[][] priceArr = p.getPriceArr();

        for (int i = 0; i < priceArr.length; i++) {
            int low = (int) priceArr[i][0];
            int high = (int) priceArr[i][1];
            double directPrice = round(priceArr[i][2]);
            double wholesalePrice = round(priceArr[i][3]);
            // int number = i+1;
            PricebookEntryState pricebookEntry = new PricebookEntryState(low, high, directPrice, wholesalePrice);
            pricebookEntry.setPricebookId(id);
            System.out.println("SET NUMBER " + i);
            pricebookEntry.setNumber(i);
            entryList.add(pricebookEntry);
        }


        return entryList;
    }

    public void editPricebookEntry(Long pricebookId, int number, int low, int high, double directPrice, double wholesalePrice) {

        PricebookEntity p = em.find(PricebookEntity.class, pricebookId);
        double[][] priceArr = p.getPriceArr();

        System.out.println("Number " + number);

        priceArr[number][0] = low;
        p.setPriceArr(priceArr);
        em.flush();

        priceArr[number][1] = high;
        p.setPriceArr(priceArr);
        em.flush();

        priceArr[number][2] = directPrice;
        p.setPriceArr(priceArr);
        em.flush();

        priceArr[number][3] = wholesalePrice;
        p.setPriceArr(priceArr);
        em.flush();


    }

    public void deletePricebook(Long pricebookId) {
        PricebookEntity p = em.find(PricebookEntity.class, pricebookId);
        p.setDeleteFlag("Y");
        em.flush();
    }

    public ProductState searchProduct(Long id) {


        ProductEntity p = em.find(ProductEntity.class, id);
        ProductState pState = new ProductState(p.getId(), p.getName(), p.getDescription(),
                p.getBasePrice(), p.getListPrice(), p.getLimitPrice(), p.getPricebook());

        return pState;
    }

    public ClientState searchClient(Long id) {

        ClientEntity c = em.find(ClientEntity.class, id);

        ClientState clState = new ClientState(c.getId(), c.getName(), c.getAddress(), c.getContactNum(),
                c.getCountry(), c.getCity(), c.getPostalCode(), c.getEmailAddress(),
                c.getBusinessType(), c.getClientType());
        clState.setIndustry(c.getIndustry());
        clState.setAnnualRevenue(c.getAnnualRevenue());
        clState.setNumOfEmployees(c.getNumOfEmployees());
        clState.setContactNum(c.getContactNum());
        clState.setAddressState(c.getAddressState());
        clState.setFaxNum(c.getFaxNum());
        clState.setWebsite(c.getWebsite());
        clState.setRating(c.getRating());
        clState.setClientType(c.getClientType());
        clState.setDateCreated(c.getDateCreated());
        clState.setDescription(c.getDescription());
        List<AddressState> addressList = new ArrayList<AddressState>();

        if (c.getClientType().equals("CU")) {
            CustomerEntity a = (CustomerEntity) c;
            BillingAddressEntity ba = new BillingAddressEntity();
            List<BillingAddressEntity> baList = a.getBillingAddress();
            for (Object p : baList) {
                BillingAddressEntity bAddress = (BillingAddressEntity) p;
                AddressState billingAddress = new AddressState(bAddress.getId(), bAddress.getBillingStreet(),
                        bAddress.getBillingCity(), bAddress.getBillingState(),
                        bAddress.getBillingCode(), bAddress.getBillingCountry(),
                        bAddress.isPrimaryAddress(), "B");
                if (bAddress.isPrimaryAddress()) {
                    ba = bAddress;
                }
                addressList.add(billingAddress);
            }

            clState.setBillingId(ba.getId());
            clState.setBillingCity(ba.getBillingCity());
            clState.setBillingCode(ba.getBillingCode());
            clState.setBillingCountry(ba.getBillingCountry());
            clState.setBillingState(ba.getBillingState());
            System.out.println("Search Client : " + clState.getBillingState());
            clState.setBillingStreet(ba.getBillingStreet());

            ShippingAddressEntity sa = new ShippingAddressEntity();
            List<ShippingAddressEntity> saList = a.getShippingAddress();
            for (Object p : saList) {
                ShippingAddressEntity sAddress = (ShippingAddressEntity) p;
                AddressState shippingAddress = new AddressState(sAddress.getId(), sAddress.getShippingStreet(),
                        sAddress.getShippingCity(), sAddress.getShippingState(),
                        sAddress.getShippingCode(), sAddress.getShippingCountry(),
                        sAddress.isPrimaryAddress(), "S");
                if (sAddress.isPrimaryAddress()) {
                    sa = sAddress;
                }
                addressList.add(shippingAddress);
            }

            clState.setShippingId(sa.getId());
            clState.setShippingCity(sa.getShippingCity());
            clState.setShippingCode(sa.getShippingCode());
            clState.setShippingCountry(sa.getShippingCountry());
            clState.setShippingState(sa.getShippingState());
            clState.setShippingStreet(sa.getShippingStreet());

            clState.setAddressList(addressList);
        }

        return clState;
    }

      public SalesDocumentState searchQuotation(Long id) {
        System.out.println("Search for quotation");
        QuotationEntity c = em.find(QuotationEntity.class, id);
        SalesDocumentState sdState = new SalesDocumentState();
        if (c != null) {

            double totalPrice = 0;

            Collection<LineEntryEntity> lineEntryList = c.getLineEntryList();
            for (Object l : lineEntryList) {
                LineEntryEntity lineEntry = (LineEntryEntity) l;
                totalPrice = totalPrice + lineEntry.getTotalLinePrice();
            }
            sdState = new SalesDocumentState(c.getId(), c.getDateIssued(),
                    c.getvalidUntil(), c.getIndicativeLeadtime(),
                    c.getClient().getId(), c.getClient().getName(),
                    c.getLineEntryList());

            sdState.setTotalPrice(totalPrice);
            sdState.setDescription(c.getDescription());
            sdState.setDocumentName(c.getDocumentName());
            sdState.setPricingType(c.getPricingType());
        }

        return sdState;
    }
      
    public SalesDocumentState searchInquiry(Long id) {
        System.out.println("Search for sales inquiry");
        SalesInquiryEntity c = em.find(SalesInquiryEntity.class, id);
        SalesDocumentState sdState =new SalesDocumentState();
        
        if (c != null) {

            double totalPrice = 0;

            Collection<LineEntryEntity> lineEntryList = c.getLineEntryList();
            for (Object l : lineEntryList) {
                LineEntryEntity lineEntry = (LineEntryEntity) l;
                totalPrice = totalPrice + lineEntry.getTotalLinePrice();
            }
            sdState = new SalesDocumentState(c.getId(), c.getDateIssued(),
                    c.getClient().getId(), c.getClient().getName(),
                    c.getStatus(), c.getLineEntryList());
            sdState.setTotalPrice(totalPrice);
            sdState.setClient(c.getClient());
            if (c.getContact() != null) {
                sdState.setContactId(c.getContact().getId());
                sdState.setContactName(c.getContact().getFirstName() + c.getContact().getLastName());
            } else {
                sdState.setContactId(Long.parseLong("0"));
                sdState.setContactName("Not yet specified");
            }

            sdState.setTotalPrice(totalPrice);
            sdState.setDescription(c.getDescription());
            sdState.setDocumentName(c.getDocumentName());
            sdState.setPricingType(c.getPricingType());


            
        }
        return sdState;
    }

    public SalesDocumentState searchPurchaseOrder(Long cid) {
        System.out.println("Search for purchase order");
        PurchaseOrderEntity c = em.find(PurchaseOrderEntity.class, cid);
        SalesDocumentState sdState = new SalesDocumentState();
        if (c != null) {

            double totalPrice = 0;
            String pricingType = c.getPricingType();
            Collection<LineEntryEntity> lineEntryList = c.getLineEntryList();
            for (Object l : lineEntryList) {
                LineEntryEntity lineEntry = (LineEntryEntity) l;
                totalPrice = totalPrice + lineEntry.getTotalLinePrice();

            }
            Long id = c.getQuotation().getId();
            sdState = new SalesDocumentState(c.getId(), c.getDateIssued(),
                    c.getClient().getId(), c.getClient().getName(),
                    c.getStatus(), c.getLineEntryList(), c.getQuotation(), id);
            sdState.setLeadTime(c.getQuotation().getIndicativeLeadtime());
            sdState.setTotalPrice(totalPrice);
            sdState.setDescription(c.getDescription());
            sdState.setDocumentName(c.getDocumentName());
            sdState.setDueDate(c.getDueDate());
            sdState.setShippingMethod(c.getShippingMethod());
            sdState.setShippingRule(c.getShippingRule());
            sdState.setInvoiceRule(c.getInvoiceRule());
            sdState.setPaymentMethod(c.getPaymentMethod());
            sdState.setFreightCostRule(c.getFreightCostRule());
            sdState.setCurrency(c.getCurrency());
            sdState.setPricingType(pricingType);

            BillingAddressEntity ba = c.getBillingAddress();
            sdState.setBillingId(ba.getId());
            sdState.setBillingStreet(ba.getBillingStreet());
            sdState.setBillingState(ba.getBillingState());
            sdState.setBillingCity(ba.getBillingCity());
            sdState.setBillingCode(ba.getBillingCode());
            sdState.setBillingCountry(ba.getBillingCountry());

            ShippingAddressEntity sa = c.getShippingAddress();
            sdState.setShippingId(sa.getId());
            sdState.setShippingStreet(sa.getShippingStreet());
            sdState.setShippingState(sa.getShippingState());
            sdState.setShippingCity(sa.getShippingCity());
            sdState.setShippingCode(sa.getShippingCode());
            sdState.setShippingCountry(sa.getShippingCountry());

        }

        return sdState;
    }

    public SalesDocumentState searchSalesOrder(Long sid) {


        System.out.println("Search for sales order");
        SalesOrderEntity c = em.find(SalesOrderEntity.class, sid);
        SalesDocumentState sdState = new SalesDocumentState();
        if (c != null) {

            double totalPrice = 0;
            String pricingType = c.getPricingType();
            Collection<LineEntryEntity> lineEntryList = c.getLineEntryList();
            for (Object l : lineEntryList) {
                LineEntryEntity lineEntry = (LineEntryEntity) l;
                totalPrice = totalPrice + lineEntry.getTotalLinePrice();
            }

            Long id = c.getPurchaseOrder().getId();
            sdState = new SalesDocumentState(c.getId(), c.getDateIssued(),
                    c.getClient().getId(), c.getClient().getName(),
                    c.getStatus(), c.getATPCheckStatus(), c.getCreditCheckStatus(),
                    c.getLineEntryList(), c.getPurchaseOrder(), id);
            sdState.setLeadTime(c.getleadTimeConfirmed());
            sdState.setTotalPrice(totalPrice);
            sdState.setDescription(c.getDescription());
            sdState.setDocumentName(c.getDocumentName());
            sdState.setDueDate(c.getDueDate());
            sdState.setShippingMethod(c.getShippingMethod());
            sdState.setShippingRule(c.getShippingRule());
            sdState.setInvoiceRule(c.getInvoiceRule());
            sdState.setPaymentMethod(c.getPaymentMethod());
            sdState.setFreightCostRule(c.getFreightCostRule());
            sdState.setCurrency(c.getCurrency());
            sdState.setPricingType(pricingType);

            BillingAddressEntity ba = c.getBillingAddress();
            sdState.setBillingId(ba.getId());
            sdState.setBillingStreet(ba.getBillingStreet());
            sdState.setBillingState(ba.getBillingState());
            sdState.setBillingCity(ba.getBillingCity());
            sdState.setBillingCode(ba.getBillingCode());
            sdState.setBillingCountry(ba.getBillingCountry());

            ShippingAddressEntity sa = c.getShippingAddress();
            sdState.setShippingId(sa.getId());
            sdState.setShippingStreet(sa.getShippingStreet());
            sdState.setShippingState(sa.getShippingState());
            sdState.setShippingCity(sa.getShippingCity());
            sdState.setShippingCode(sa.getShippingCode());
            sdState.setShippingCountry(sa.getShippingCountry());

        }

        return sdState;

    }

    public List<AddressState> getBillingAddressList() {

        Query q = em.createQuery("SELECT a from BillingAddressEntity a");
        List<AddressState> addressList = new ArrayList<AddressState>();

        for (Object o : q.getResultList()) {
            BillingAddressEntity ba = (BillingAddressEntity) o;
            AddressState bAddress = new AddressState(ba.getId(), ba.getBillingStreet(),
                    ba.getBillingCity(), ba.getBillingState(), ba.getBillingCode(), ba.getBillingCountry(),
                    ba.isPrimaryAddress(), "B");
            addressList.add(bAddress);

        }

        return addressList;

    }

    public List<AddressState> getShippingAddressList() {

        Query q = em.createQuery("SELECT a from ShippingAddressEntity a");
        List<AddressState> addressList = new ArrayList<AddressState>();

        for (Object o : q.getResultList()) {
            ShippingAddressEntity ba = (ShippingAddressEntity) o;
            AddressState bAddress = new AddressState(ba.getId(), ba.getShippingStreet(),
                    ba.getShippingCity(), ba.getShippingState(), ba.getShippingCode(), ba.getShippingCountry(),
                    ba.isPrimaryAddress(), "S");
            addressList.add(bAddress);

        }
        return addressList;
    }

    public AddressState searchShippingAddress(Long id) {

        ShippingAddressEntity sa = em.find(ShippingAddressEntity.class, id);
        AddressState sAddress = new AddressState();
        if (sa != null) {
            sAddress = new AddressState(sa.getId(), sa.getShippingStreet(),
                    sa.getShippingCity(), sa.getShippingState(), sa.getShippingCode(), sa.getShippingCountry(),
                    sa.isPrimaryAddress(), "S");
        }

        return sAddress;
    }

    public AddressState searchBillingAddress(Long id) {

        BillingAddressEntity sa = em.find(BillingAddressEntity.class, id);
        AddressState sAddress = new AddressState();
        if (sa != null) {
            sAddress = new AddressState(sa.getId(), sa.getBillingStreet(),
                    sa.getBillingCity(), sa.getBillingState(), sa.getBillingCode(), sa.getBillingCountry(),
                    sa.isPrimaryAddress(), "B");
        }

        return sAddress;
    }

    public List<SalesDocumentState> viewQuotationsforPO() {
        System.out.println("viewQuotations");

        Query q = em.createQuery("SELECT c FROM QuotationEntity c");
        List stateList = new ArrayList();

        if (q.getResultList() != null) {
            System.out.println("Result list not null");
        }
        for (Object o : q.getResultList()) {
            QuotationEntity c = (QuotationEntity) o;
            if (c.getDocumentType().equals("QN") && c.getDeleteFlag().equals("N") && !c.getStatus().equals("Converted")
                    && !c.getStatus().equals("Voided") /*&& !c.getStatus().equals("Approved")*/
                    && c.getClient().getDeleteFlag().equals("N") && !c.isReferred() && smb.checkClientStatus(c.getClient()) /* && c.getReservationEntity()!=null*/) {
                double price;
                double totalPrice = 0;
                String type = c.getPricingType();
                Collection<LineEntryEntity> lineEntryList = c.getLineEntryList();
                for (Object l : lineEntryList) {
                    LineEntryEntity lineEntry = (LineEntryEntity) l;
                    totalPrice = totalPrice + lineEntry.getTotalLinePrice();

                }

                SalesDocumentState sdState = new SalesDocumentState(c.getId(), c.getDateIssued(),
                        c.getvalidUntil(), c.getIndicativeLeadtime(),
                        c.getClient().getId(), c.getClient().getName(),
                        c.getLineEntryList());

                sdState.setTotalPrice(totalPrice);
                sdState.setDescription(c.getDescription());
                sdState.setDocumentName(c.getDocumentName());
                sdState.setPricingType(type);
                sdState.setReferred(c.isReferred());

                stateList.add(sdState);
            }
        }
        return stateList;
    }

    public List<SalesDocumentState> viewPurchaseOrdersforSO() {
        System.out.println("viewPurchaseOrdersforSO");

        Query q = em.createQuery("SELECT c FROM PurchaseOrderEntity c");
        List<SalesDocumentState> stateList = new ArrayList();

        for (Object o : q.getResultList()) {
            PurchaseOrderEntity c = (PurchaseOrderEntity) o;
            if (c.getDocumentType().equals("PO") && c.getDeleteFlag().equals("N") && !c.getStatus().equals("Converted")
                    && c.getClient().getDeleteFlag().equals("N") && !c.isReferred()
                    && !c.getStatus().equals("Voided") && !c.getStatus().equals("Rejected") /*&& !c.getStatus().equals("Approved")*//*&& c.getReservationEntity()!=null*/
                    && smb.checkClientStatus(c.getClient())) {
                double totalPrice = 0;
                double price;
                String type = c.getPricingType();

                Collection<LineEntryEntity> lineEntryList = c.getLineEntryList();
                for (Object l : lineEntryList) {
                    LineEntryEntity lineEntry = (LineEntryEntity) l;
                    totalPrice = totalPrice + lineEntry.getTotalLinePrice();
                }

                Long id = c.getQuotation().getId();
                SalesDocumentState sdState = new SalesDocumentState(c.getId(), c.getDateIssued(),
                        c.getClient().getId(), c.getClient().getName(),
                        c.getStatus(), c.getLineEntryList(), c.getQuotation(), id);
                sdState.setLeadTime(c.getQuotation().getIndicativeLeadtime());
                sdState.setTotalPrice(totalPrice);
                sdState.setDescription(c.getDescription());
                sdState.setDocumentName(c.getDocumentName());
                sdState.setDueDate(c.getDueDate());
                sdState.setShippingMethod(c.getShippingMethod());
                sdState.setShippingRule(c.getShippingRule());
                sdState.setInvoiceRule(c.getInvoiceRule());
                sdState.setPaymentMethod(c.getPaymentMethod());
                sdState.setFreightCostRule(c.getFreightCostRule());
                sdState.setCurrency(c.getCurrency());
                sdState.setPricingType(type);
                sdState.setReferred(c.isReferred());
                if (c.getContact() != null) {
                    sdState.setContactId(c.getContact().getId());
                    sdState.setContactName(c.getContact().getFirstName() + c.getContact().getLastName());
                } else {
                    sdState.setContactId(Long.parseLong("0"));
                    sdState.setContactName("Not yet specified");
                }
                BillingAddressEntity ba = c.getBillingAddress();
                sdState.setBillingId(ba.getId());
                sdState.setBillingStreet(ba.getBillingStreet());
                sdState.setBillingState(ba.getBillingState());
                System.out.println("View PO for SO : " + ba.getBillingState());
                sdState.setBillingCity(ba.getBillingCity());
                sdState.setBillingCode(ba.getBillingCode());
                sdState.setBillingCountry(ba.getBillingCountry());

                ShippingAddressEntity sa = c.getShippingAddress();
                sdState.setShippingId(sa.getId());
                sdState.setShippingStreet(sa.getShippingStreet());
                sdState.setShippingState(sa.getShippingState());
                sdState.setShippingCity(sa.getShippingCity());
                sdState.setShippingCode(sa.getShippingCode());
                sdState.setShippingCountry(sa.getShippingCountry());

                stateList.add(sdState);
            }
        }
        return stateList;
    }

    public List<SalesDocumentState> viewSalesOrdersForDO() {
        System.out.println("viewSalesOrders");


        Query q = em.createQuery("SELECT c FROM SalesOrderEntity c");
        List stateList = new ArrayList();

        for (Object o : q.getResultList()) {
            SalesOrderEntity c = (SalesOrderEntity) o;
            if (c.getDocumentType().equals("SO") && c.getDeleteFlag().equals("N")
                    && c.getClient().getDeleteFlag().equals("N") && c.getStatus().equals("Approved")
                    && smb.checkClientStatus(c.getClient())) {
                double totalPrice = 0;
                double price;
                String type = c.getPricingType();

                Collection<LineEntryEntity> lineEntryList = c.getLineEntryList();
                for (Object l : lineEntryList) {
                    LineEntryEntity lineEntry = (LineEntryEntity) l;

                    totalPrice = totalPrice + lineEntry.getTotalLinePrice();
                }

                SalesDocumentState sdState = new SalesDocumentState(c.getId(), c.getDateIssued(),
                        c.getClient().getId(), c.getClient().getName(),
                        c.getStatus(), c.getATPCheckStatus(), c.getCreditCheckStatus(),
                        c.getLineEntryList(), c.getPurchaseOrder(), c.getPurchaseOrder().getId());

                sdState.setTotalPrice(totalPrice);
                sdState.setDescription(c.getDescription());
                sdState.setLeadTime(c.getPurchaseOrder().getQuotation().getIndicativeLeadtime());
                sdState.setConfirmedLeadTime(c.getleadTimeConfirmed());
                sdState.setDocumentName(c.getDocumentName());
                sdState.setDueDate(c.getDueDate());
                sdState.setShippingMethod(c.getShippingMethod());
                sdState.setShippingRule(c.getShippingRule());
                sdState.setInvoiceRule(c.getInvoiceRule());
                sdState.setPaymentMethod(c.getPaymentMethod());
                sdState.setFreightCostRule(c.getFreightCostRule());
                sdState.setCurrency(c.getCurrency());
                sdState.setApproved(c.isIsApproved());
                sdState.setVoided(c.isIsVoided());
                sdState.setCompleted(c.isIsCompleted());
                sdState.setRejected(c.isIsRejected());
                sdState.setCashInAdvanced(c.isCashInAdvanced());
                sdState.setPricingType(type);
                sdState.setReferred(c.isReferred());
                
                if (c.getContact() != null) {
                    sdState.setContactId(c.getContact().getId());
                    sdState.setContactName(c.getContact().getFirstName() + c.getContact().getLastName());
                } else {
                    sdState.setContactId(Long.parseLong("0"));
                    sdState.setContactName("Not yet specified");
                }
                BillingAddressEntity ba = c.getBillingAddress();
                sdState.setBillingId(ba.getId());
                sdState.setBillingStreet(ba.getBillingStreet());
                sdState.setBillingState(ba.getBillingState());
                System.out.println("View PO : " + sdState.getBillingState());
                sdState.setBillingCity(ba.getBillingCity());
                sdState.setBillingCode(ba.getBillingCode());
                sdState.setBillingCountry(ba.getBillingCountry());

                ShippingAddressEntity sa = c.getShippingAddress();
                sdState.setShippingId(sa.getId());
                sdState.setShippingStreet(sa.getShippingStreet());
                sdState.setShippingState(sa.getShippingState());
                sdState.setShippingCity(sa.getShippingCity());
                sdState.setShippingCode(sa.getShippingCode());
                sdState.setShippingCountry(sa.getShippingCountry());


                stateList.add(sdState);

            }
        }
        return stateList;
    }

    public List<DeliveryOrderState> viewDeliveryOrders() {
        System.out.println("viewDeliveryOrders");

        Query q = em.createQuery("SELECT c FROM DeliveryOrderEntity c");
        List<DeliveryOrderState> stateList = new ArrayList();
        double totalPrice = 0;
        for (Object o : q.getResultList()) {
            DeliveryOrderEntity c = (DeliveryOrderEntity) o;
            if (c.getDeleteFlag().equals("N") && smb.checkClientStatus(c.getCustomer())) {

                List<LineEntryEntity> lineEntryList = c.getLineEntryList();
                for (Object l : lineEntryList) {
                    LineEntryEntity lineEntry = (LineEntryEntity) l;
                    totalPrice = totalPrice + lineEntry.getTotalLinePrice();
                }

                DeliveryOrderState doState = new DeliveryOrderState(c.getId(), c.getSalesOrder().getId(),
                        c.getStatus(), c.getShippingMethod(), c.getShippingRule(),
                        c.getDueDate(), c.getDateIssued(), c.getCheckBy(),
                        c.getFreightCostRule());
                totalPrice = round(totalPrice);
                
                doState.setPricingType(c.getPricingType());
                doState.setPaymentMethod(c.getPaymentMethod());
                doState.setDescription(c.getDescription());
                doState.setClientId(c.getCustomer().getId());
                doState.setClientName(c.getCustomer().getName());

                doState.setDocumentName(c.getDocumentName());
                if (c.getContact() != null) {
                    doState.setContactId(c.getContact().getId());
                    doState.setContactName(c.getContact().getFirstName() + c.getContact().getLastName());
                } else {
                    doState.setContactId(Long.parseLong("0"));
                    doState.setContactName("Not yet specified");
                }

                BillingAddressEntity ba = c.getBillingAddress();
                doState.setBillingId(ba.getId());
                doState.setBillingStreet(ba.getBillingStreet());
                doState.setBillingState(ba.getBillingState());
                doState.setBillingCity(ba.getBillingCity());
                doState.setBillingCode(ba.getBillingCode());
                doState.setBillingCountry(ba.getBillingCountry());

                ShippingAddressEntity sa = c.getShippingAddress();
                doState.setShippingId(sa.getId());
                doState.setShippingStreet(sa.getShippingStreet());
                doState.setShippingState(sa.getShippingState());
                doState.setShippingCity(sa.getShippingCity());
                doState.setShippingCode(sa.getShippingCode());
                doState.setShippingCountry(sa.getShippingCountry());

                stateList.add(doState);
            }

        }
        return stateList;
    }
    
    public void updateQuotationStatus(Long id, String status){
        QuotationEntity qo = em.find(QuotationEntity.class, id);
        if(status.equals("Voided")){
        if(qo.getBackOrder()!=null){
                
            this.annulReservationsOnSalesOrder(qo.getBackOrder().getId());
          
        }
        qo.setStatus(status);
        }
        em.flush();
    }
    
      public void updateSalesOrderStatus(Long id, String status){
       SalesOrderEntity qo = em.find(SalesOrderEntity.class, id);
        
       if(status.equals("Voided")){
       if(qo.getBackOrder()!=null){
                for(Object o : qo.getDeliveryOrderList()){
                    DeliveryOrderEntity doe = (DeliveryOrderEntity) o;
                    imm.withdrawDeliveryOrder(doe.getId());    
                }
                
            this.annulReservationsOnSalesOrder(qo.getBackOrder().getId());
        }
       }
        qo.setStatus(status);
        em.flush();
    }
    
    

    public void checkSalesDocumentValidity(){
        Query q = em.createQuery("Select a from QuotationEntity a where a.deleteFlag='N'");
        
        for(Object o : q.getResultList()){
            QuotationEntity qn = (QuotationEntity) o;
  
            Date dateDue =  qn.getvalidUntil();
            SimpleDateFormat formatter = new SimpleDateFormat("dd/MM/yyyy");
            String d1 = formatter.format(dateDue);
            
            System.out.println("Get date now");
            Calendar currentDate = Calendar.getInstance();
            Date dateNow = currentDate.getTime();
            String d2 = formatter.format(dateNow);
            
            if(d1.equals(d2)){
                updateQuotationStatus(qn.getId(), "Voided");
            }
        }
        
        Query q2 = em.createQuery("Select a from PurchaseOrderEntity a where a.deleteFlag='N'");
        
        for(Object o : q2.getResultList()){
            PurchaseOrderEntity qn = (PurchaseOrderEntity) o;
  
            Date dateDue =  qn.getDueDate();
            SimpleDateFormat formatter = new SimpleDateFormat("dd/MM/yyyy");
            String d1 = formatter.format(dateDue);
            
            System.out.println("Get date now");
            Calendar currentDate = Calendar.getInstance();
            Date dateNow = currentDate.getTime();
            String d2 = formatter.format(dateNow);
            
            if(d1.equals(d2)){
                updatePurchaseOrderStatus(qn.getId(), "Voided");
            }
            
        }
        
        Query q3 = em.createQuery("Select a from SalesOrderEntity a where a.deleteFlag='N'");

        for (Object o : q3.getResultList()) {
            SalesOrderEntity qn = (SalesOrderEntity) o;

            Date dateDue = qn.getDueDate();
            SimpleDateFormat formatter = new SimpleDateFormat("dd/MM/yyyy");
            String d1 = formatter.format(dateDue);

            System.out.println("Get date now");
            Calendar currentDate = Calendar.getInstance();
            Date dateNow = currentDate.getTime();
            String d2 = formatter.format(dateNow);

            if (d1.equals(d2)) {
                updateSalesOrderStatus(qn.getId(), "Voided");
            }
        }
        
    }
    
    protected void confirmReservationsOnSalesOrder(Long backOrderId) {
        pmb.confirmBackOrder(backOrderId);
    }

    protected void annulReservationsOnSalesOrder(Long backOrderId) {
        pmb.withdrawBackOrder(backOrderId);
    }

}
